[HLRC] Add GetRollupIndexCaps API (#35102)
Also refactors the caps response tests a bit to share the same abstract class to reduce duplication of test code
This commit is contained in:
parent
e7896bcefc
commit
2da239fb5e
|
@ -22,6 +22,8 @@ package org.elasticsearch.client;
|
|||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.client.rollup.DeleteRollupJobRequest;
|
||||
import org.elasticsearch.client.rollup.DeleteRollupJobResponse;
|
||||
import org.elasticsearch.client.rollup.GetRollupIndexCapsRequest;
|
||||
import org.elasticsearch.client.rollup.GetRollupIndexCapsResponse;
|
||||
import org.elasticsearch.client.rollup.GetRollupJobRequest;
|
||||
import org.elasticsearch.client.rollup.GetRollupJobResponse;
|
||||
import org.elasticsearch.client.rollup.GetRollupCapsRequest;
|
||||
|
@ -219,4 +221,40 @@ public class RollupClient {
|
|||
listener,
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Rollup Index Capabilities of a rollup index or pattern
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-get-rollup-index-caps.html">
|
||||
* 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 GetRollupIndexCapsResponse getRollupIndexCapabilities(GetRollupIndexCapsRequest request,
|
||||
RequestOptions options) throws IOException {
|
||||
return restHighLevelClient.performRequestAndParseEntity(request,
|
||||
RollupRequestConverters::getRollupIndexCaps,
|
||||
options,
|
||||
GetRollupIndexCapsResponse::fromXContent,
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously Get the Rollup Index Capabilities of a rollup index or pattern
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/master/rollup-get-rollup-index-caps.html">
|
||||
* 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 getRollupIndexCapabilitiesAsync(GetRollupIndexCapsRequest request, RequestOptions options,
|
||||
ActionListener<GetRollupIndexCapsResponse> listener) {
|
||||
restHighLevelClient.performRequestAsyncAndParseEntity(request,
|
||||
RollupRequestConverters::getRollupIndexCaps,
|
||||
options,
|
||||
GetRollupIndexCapsResponse::fromXContent,
|
||||
listener,
|
||||
Collections.emptySet());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.http.client.methods.HttpPost;
|
|||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.elasticsearch.client.rollup.DeleteRollupJobRequest;
|
||||
import org.elasticsearch.client.rollup.GetRollupCapsRequest;
|
||||
import org.elasticsearch.client.rollup.GetRollupIndexCapsRequest;
|
||||
import org.elasticsearch.client.rollup.GetRollupJobRequest;
|
||||
import org.elasticsearch.client.rollup.PutRollupJobRequest;
|
||||
import org.elasticsearch.client.rollup.StartRollupJobRequest;
|
||||
|
@ -85,4 +86,14 @@ final class RollupRequestConverters {
|
|||
request.setEntity(createEntity(getRollupCapsRequest, REQUEST_BODY_CONTENT_TYPE));
|
||||
return request;
|
||||
}
|
||||
|
||||
static Request getRollupIndexCaps(final GetRollupIndexCapsRequest getRollupIndexCapsRequest) throws IOException {
|
||||
String endpoint = new RequestConverters.EndpointBuilder()
|
||||
.addCommaSeparatedPathParts(getRollupIndexCapsRequest.indices())
|
||||
.addPathPartAsIs("_xpack", "rollup", "data")
|
||||
.build();
|
||||
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
|
||||
request.setEntity(createEntity(getRollupIndexCapsRequest, REQUEST_BODY_CONTENT_TYPE));
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
*/
|
||||
package org.elasticsearch.client.rollup;
|
||||
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -30,7 +26,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class GetRollupCapsResponse implements ToXContentObject {
|
||||
public class GetRollupCapsResponse {
|
||||
|
||||
private final Map<String, RollableIndexCaps> jobs;
|
||||
|
||||
|
@ -42,16 +38,6 @@ public class GetRollupCapsResponse implements ToXContentObject {
|
|||
return jobs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
builder.startObject();
|
||||
for (Map.Entry<String, RollableIndexCaps> entry : jobs.entrySet()) {
|
||||
entry.getValue().toXContent(builder, params);
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static GetRollupCapsResponse fromXContent(final XContentParser parser) throws IOException {
|
||||
Map<String, RollableIndexCaps> jobs = new HashMap<>();
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
|
@ -84,9 +70,4 @@ public class GetRollupCapsResponse implements ToXContentObject {
|
|||
GetRollupCapsResponse other = (GetRollupCapsResponse) obj;
|
||||
return Objects.equals(jobs, other.jobs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return Strings.toString(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.rollup;
|
||||
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.client.Validatable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public class GetRollupIndexCapsRequest implements Validatable, ToXContentObject {
|
||||
private static final String INDICES = "indices";
|
||||
private static final String INDICES_OPTIONS = "indices_options";
|
||||
|
||||
private String[] indices;
|
||||
private IndicesOptions options;
|
||||
|
||||
public GetRollupIndexCapsRequest(final String... indices) {
|
||||
this(indices, IndicesOptions.STRICT_EXPAND_OPEN_FORBID_CLOSED);
|
||||
}
|
||||
|
||||
public GetRollupIndexCapsRequest(final String[] indices, final IndicesOptions options) {
|
||||
if (indices == null || indices.length == 0) {
|
||||
throw new IllegalArgumentException("[indices] must not be null or empty");
|
||||
}
|
||||
for (String index : indices) {
|
||||
if (Strings.isNullOrEmpty(index)) {
|
||||
throw new IllegalArgumentException("[index] must not be null or empty");
|
||||
}
|
||||
}
|
||||
this.indices = indices;
|
||||
this.options = Objects.requireNonNull(options);
|
||||
}
|
||||
|
||||
public IndicesOptions indicesOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public String[] indices() {
|
||||
return indices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
{
|
||||
builder.array(INDICES, indices);
|
||||
builder.startObject(INDICES_OPTIONS);
|
||||
{
|
||||
options.toXContent(builder, params);
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(Arrays.hashCode(indices), options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
GetRollupIndexCapsRequest other = (GetRollupIndexCapsRequest) obj;
|
||||
return Arrays.equals(indices, other.indices)
|
||||
&& Objects.equals(options, other.options);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.rollup;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class GetRollupIndexCapsResponse {
|
||||
|
||||
private final Map<String, RollableIndexCaps> jobs;
|
||||
|
||||
public GetRollupIndexCapsResponse(final Map<String, RollableIndexCaps> jobs) {
|
||||
this.jobs = Collections.unmodifiableMap(Objects.requireNonNull(jobs));
|
||||
}
|
||||
|
||||
public Map<String, RollableIndexCaps> getJobs() {
|
||||
return jobs;
|
||||
}
|
||||
|
||||
public static GetRollupIndexCapsResponse fromXContent(final XContentParser parser) throws IOException {
|
||||
Map<String, RollableIndexCaps> jobs = new HashMap<>();
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
if (token.equals(XContentParser.Token.START_OBJECT)) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token.equals(XContentParser.Token.FIELD_NAME)) {
|
||||
String pattern = parser.currentName();
|
||||
|
||||
RollableIndexCaps cap = RollableIndexCaps.PARSER.apply(pattern).apply(parser, null);
|
||||
jobs.put(pattern, cap);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new GetRollupIndexCapsResponse(jobs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(jobs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
GetRollupIndexCapsResponse other = (GetRollupIndexCapsResponse) obj;
|
||||
return Objects.equals(jobs, other.jobs);
|
||||
}
|
||||
}
|
|
@ -33,6 +33,8 @@ import org.elasticsearch.client.rollup.DeleteRollupJobRequest;
|
|||
import org.elasticsearch.client.rollup.DeleteRollupJobResponse;
|
||||
import org.elasticsearch.client.rollup.GetRollupCapsRequest;
|
||||
import org.elasticsearch.client.rollup.GetRollupCapsResponse;
|
||||
import org.elasticsearch.client.rollup.GetRollupIndexCapsRequest;
|
||||
import org.elasticsearch.client.rollup.GetRollupIndexCapsResponse;
|
||||
import org.elasticsearch.client.rollup.GetRollupJobRequest;
|
||||
import org.elasticsearch.client.rollup.GetRollupJobResponse;
|
||||
import org.elasticsearch.client.rollup.GetRollupJobResponse.IndexerState;
|
||||
|
@ -348,4 +350,116 @@ public class RollupIT extends ESRestHighLevelClientTestCase {
|
|||
List<Map<String, Object>> valueCaps = fieldCaps.get("value").getAggs();
|
||||
assertThat(valueCaps.size(), equalTo(SUPPORTED_METRICS.size()));
|
||||
}
|
||||
|
||||
public void testGetRollupIndexCaps() throws Exception {
|
||||
final Set<Integer> values = new HashSet<>();
|
||||
double sum = 0.0d;
|
||||
int max = Integer.MIN_VALUE;
|
||||
int min = Integer.MAX_VALUE;
|
||||
|
||||
final BulkRequest bulkRequest = new BulkRequest();
|
||||
bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
|
||||
for (int minute = 0; minute < 60; minute++) {
|
||||
for (int second = 0; second < 60; second = second + 10) {
|
||||
final int value = randomIntBetween(0, 100);
|
||||
|
||||
final IndexRequest indexRequest = new IndexRequest("docs", "doc");
|
||||
indexRequest.source(jsonBuilder()
|
||||
.startObject()
|
||||
.field("value", value)
|
||||
.field("date", String.format(Locale.ROOT, "2018-01-01T00:%02d:%02dZ", minute, second))
|
||||
.endObject());
|
||||
bulkRequest.add(indexRequest);
|
||||
|
||||
values.add(value);
|
||||
sum += value;
|
||||
if (value > max) {
|
||||
max = value;
|
||||
}
|
||||
if (value < min) {
|
||||
min = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final int numDocs = bulkRequest.numberOfActions();
|
||||
|
||||
BulkResponse bulkResponse = highLevelClient().bulk(bulkRequest, RequestOptions.DEFAULT);
|
||||
assertEquals(RestStatus.OK, bulkResponse.status());
|
||||
if (bulkResponse.hasFailures()) {
|
||||
for (BulkItemResponse itemResponse : bulkResponse.getItems()) {
|
||||
if (itemResponse.isFailed()) {
|
||||
logger.fatal(itemResponse.getFailureMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
assertFalse(bulkResponse.hasFailures());
|
||||
|
||||
RefreshResponse refreshResponse = highLevelClient().indices().refresh(new RefreshRequest("docs"), RequestOptions.DEFAULT);
|
||||
assertEquals(0, refreshResponse.getFailedShards());
|
||||
|
||||
final String id = randomAlphaOfLength(10);
|
||||
final String indexPattern = randomFrom("docs", "d*", "doc*");
|
||||
final String rollupIndex = randomFrom("rollup", "test");
|
||||
final String cron = "*/1 * * * * ?";
|
||||
final int pageSize = randomIntBetween(numDocs, numDocs * 10);
|
||||
// TODO expand this to also test with histogram and terms?
|
||||
final GroupConfig groups = new GroupConfig(new DateHistogramGroupConfig("date", DateHistogramInterval.DAY));
|
||||
final List<MetricConfig> metrics = Collections.singletonList(new MetricConfig("value", SUPPORTED_METRICS));
|
||||
final TimeValue timeout = TimeValue.timeValueSeconds(randomIntBetween(30, 600));
|
||||
|
||||
PutRollupJobRequest putRollupJobRequest =
|
||||
new PutRollupJobRequest(new RollupJobConfig(id, indexPattern, rollupIndex, cron, pageSize, groups, metrics, timeout));
|
||||
|
||||
final RollupClient rollupClient = highLevelClient().rollup();
|
||||
PutRollupJobResponse response = execute(putRollupJobRequest, rollupClient::putRollupJob, rollupClient::putRollupJobAsync);
|
||||
assertTrue(response.isAcknowledged());
|
||||
|
||||
// wait for the PutJob api to create the index w/ metadata
|
||||
highLevelClient().cluster().health(new ClusterHealthRequest(rollupIndex).waitForYellowStatus(), RequestOptions.DEFAULT);
|
||||
|
||||
GetRollupIndexCapsRequest getRollupIndexCapsRequest = new GetRollupIndexCapsRequest(rollupIndex);
|
||||
GetRollupIndexCapsResponse capsResponse = highLevelClient().rollup()
|
||||
.getRollupIndexCapabilities(getRollupIndexCapsRequest, RequestOptions.DEFAULT);
|
||||
|
||||
assertNotNull(capsResponse);
|
||||
Map<String, RollableIndexCaps> rolledPatterns = capsResponse.getJobs();
|
||||
assertThat(rolledPatterns.size(), equalTo(1));
|
||||
|
||||
RollableIndexCaps docsPattern = rolledPatterns.get(rollupIndex);
|
||||
assertThat(docsPattern.getIndexName(), equalTo(rollupIndex));
|
||||
|
||||
List<RollupJobCaps> rollupJobs = docsPattern.getJobCaps();
|
||||
assertThat(rollupJobs.size(), equalTo(1));
|
||||
|
||||
RollupJobCaps jobCaps = rollupJobs.get(0);
|
||||
assertThat(jobCaps.getJobID(), equalTo(id));
|
||||
assertThat(jobCaps.getRollupIndex(), equalTo(rollupIndex));
|
||||
assertThat(jobCaps.getIndexPattern(), equalTo(indexPattern));
|
||||
|
||||
Map<String, RollupJobCaps.RollupFieldCaps> fieldCaps = jobCaps.getFieldCaps();
|
||||
|
||||
List<Map<String, Object>> timestampCaps = fieldCaps.get("date").getAggs();
|
||||
for (Map.Entry<String, Object> entry : timestampCaps.get(0).entrySet()) {
|
||||
switch (entry.getKey()) {
|
||||
case "agg":
|
||||
assertThat(entry.getValue(), equalTo("date_histogram"));
|
||||
break;
|
||||
case "delay":
|
||||
assertThat(entry.getValue(), equalTo("foo"));
|
||||
break;
|
||||
case "interval":
|
||||
assertThat(entry.getValue(), equalTo("1d"));
|
||||
break;
|
||||
case "time_zone":
|
||||
assertThat(entry.getValue(), equalTo("UTC"));
|
||||
break;
|
||||
default:
|
||||
fail("Unknown field cap: [" + entry.getKey() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
List<Map<String, Object>> valueCaps = fieldCaps.get("value").getAggs();
|
||||
assertThat(valueCaps.size(), equalTo(SUPPORTED_METRICS.size()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,52 +18,13 @@
|
|||
*/
|
||||
package org.elasticsearch.client.rollup;
|
||||
|
||||
import org.elasticsearch.client.rollup.job.config.DateHistogramGroupConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.GroupConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.HistogramGroupConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.MetricConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.RollupJobConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.RollupJobConfigTests;
|
||||
import org.elasticsearch.client.rollup.job.config.TermsGroupConfig;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.HistogramAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
|
||||
import org.elasticsearch.test.AbstractXContentTestCase;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
|
||||
public class GetRollupCapsResponseTests extends AbstractXContentTestCase<GetRollupCapsResponse> {
|
||||
|
||||
private Map<String, RollableIndexCaps> indices;
|
||||
|
||||
@Before
|
||||
private void setupIndices() throws IOException {
|
||||
int numIndices = randomIntBetween(1,5);
|
||||
indices = new HashMap<>(numIndices);
|
||||
for (int i = 0; i < numIndices; i++) {
|
||||
String indexName = "index_" + randomAlphaOfLength(10);
|
||||
int numJobs = randomIntBetween(1,5);
|
||||
List<RollupJobCaps> jobs = new ArrayList<>(numJobs);
|
||||
for (int j = 0; j < numJobs; j++) {
|
||||
RollupJobConfig config = RollupJobConfigTests.randomRollupJobConfig(randomAlphaOfLength(10));
|
||||
jobs.add(new RollupJobCaps(config.getId(), config.getIndexPattern(),
|
||||
config.getRollupIndex(), createRollupFieldCaps(config)));
|
||||
}
|
||||
RollableIndexCaps cap = new RollableIndexCaps(indexName, jobs);
|
||||
indices.put(indexName, cap);
|
||||
}
|
||||
}
|
||||
public class GetRollupCapsResponseTests extends RollupCapsResponseTestCase<GetRollupCapsResponse> {
|
||||
|
||||
@Override
|
||||
protected GetRollupCapsResponse createTestInstance() {
|
||||
|
@ -71,82 +32,16 @@ public class GetRollupCapsResponseTests extends AbstractXContentTestCase<GetRoll
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsUnknownFields() {
|
||||
return false;
|
||||
protected void toXContent(GetRollupCapsResponse response, XContentBuilder builder) throws IOException {
|
||||
builder.startObject();
|
||||
for (Map.Entry<String, RollableIndexCaps> entry : response.getJobs().entrySet()) {
|
||||
entry.getValue().toXContent(builder, null);
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GetRollupCapsResponse doParseInstance(final XContentParser parser) throws IOException {
|
||||
protected GetRollupCapsResponse fromXContent(XContentParser parser) throws IOException {
|
||||
return GetRollupCapsResponse.fromXContent(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifted from core's RollupJobCaps, so that we can test without having to include this actual logic in the request
|
||||
*/
|
||||
private static Map<String, RollupJobCaps.RollupFieldCaps> createRollupFieldCaps(final RollupJobConfig rollupJobConfig) {
|
||||
final Map<String, List<Map<String, Object>>> tempFieldCaps = new HashMap<>();
|
||||
|
||||
final GroupConfig groupConfig = rollupJobConfig.getGroupConfig();
|
||||
if (groupConfig != null) {
|
||||
// Create RollupFieldCaps for the date histogram
|
||||
final DateHistogramGroupConfig dateHistogram = groupConfig.getDateHistogram();
|
||||
final Map<String, Object> dateHistogramAggCap = new HashMap<>();
|
||||
dateHistogramAggCap.put("agg", DateHistogramAggregationBuilder.NAME);
|
||||
dateHistogramAggCap.put("interval", dateHistogram.getInterval().toString());
|
||||
if (dateHistogram.getDelay() != null) {
|
||||
dateHistogramAggCap.put("delay", dateHistogram.getDelay().toString());
|
||||
}
|
||||
dateHistogramAggCap.put("time_zone", dateHistogram.getTimeZone());
|
||||
|
||||
List<Map<String, Object>> dateAggCaps = tempFieldCaps.getOrDefault(dateHistogram.getField(), new ArrayList<>());
|
||||
dateAggCaps.add(dateHistogramAggCap);
|
||||
tempFieldCaps.put(dateHistogram.getField(), dateAggCaps);
|
||||
|
||||
// Create RollupFieldCaps for the histogram
|
||||
final HistogramGroupConfig histogram = groupConfig.getHistogram();
|
||||
if (histogram != null) {
|
||||
final Map<String, Object> histogramAggCap = new HashMap<>();
|
||||
histogramAggCap.put("agg", HistogramAggregationBuilder.NAME);
|
||||
histogramAggCap.put("interval", histogram.getInterval());
|
||||
Arrays.stream(rollupJobConfig.getGroupConfig().getHistogram().getFields()).forEach(field -> {
|
||||
List<Map<String, Object>> caps = tempFieldCaps.getOrDefault(field, new ArrayList<>());
|
||||
caps.add(histogramAggCap);
|
||||
tempFieldCaps.put(field, caps);
|
||||
});
|
||||
}
|
||||
|
||||
// Create RollupFieldCaps for the term
|
||||
final TermsGroupConfig terms = groupConfig.getTerms();
|
||||
if (terms != null) {
|
||||
final Map<String, Object> termsAggCap = singletonMap("agg", TermsAggregationBuilder.NAME);
|
||||
Arrays.stream(rollupJobConfig.getGroupConfig().getTerms().getFields()).forEach(field -> {
|
||||
List<Map<String, Object>> caps = tempFieldCaps.getOrDefault(field, new ArrayList<>());
|
||||
caps.add(termsAggCap);
|
||||
tempFieldCaps.put(field, caps);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Create RollupFieldCaps for the metrics
|
||||
final List<MetricConfig> metricsConfig = rollupJobConfig.getMetricsConfig();
|
||||
if (metricsConfig.size() > 0) {
|
||||
rollupJobConfig.getMetricsConfig().forEach(metricConfig -> {
|
||||
final List<Map<String, Object>> metrics = metricConfig.getMetrics().stream()
|
||||
.map(metric -> singletonMap("agg", (Object) metric))
|
||||
.collect(Collectors.toList());
|
||||
metrics.forEach(m -> {
|
||||
List<Map<String, Object>> caps = tempFieldCaps
|
||||
.getOrDefault(metricConfig.getField(), new ArrayList<>());
|
||||
caps.add(m);
|
||||
tempFieldCaps.put(metricConfig.getField(), caps);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(tempFieldCaps.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey,
|
||||
e -> new RollupJobCaps.RollupFieldCaps(e.getValue()))));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.rollup;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class GetRollupIndexCapsRequestTests extends ESTestCase {
|
||||
|
||||
public void testNullOrEmptyIndices() {
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> new GetRollupIndexCapsRequest((String[]) null));
|
||||
assertThat(e.getMessage(), equalTo("[indices] must not be null or empty"));
|
||||
|
||||
String[] indices = new String[]{};
|
||||
e = expectThrows(IllegalArgumentException.class, () -> new GetRollupIndexCapsRequest(indices));
|
||||
assertThat(e.getMessage(), equalTo("[indices] must not be null or empty"));
|
||||
|
||||
e = expectThrows(IllegalArgumentException.class, () -> new GetRollupIndexCapsRequest(new String[]{"foo", null}));
|
||||
assertThat(e.getMessage(), equalTo("[index] must not be null or empty"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.rollup;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class GetRollupIndexCapsResponseTests extends RollupCapsResponseTestCase<GetRollupIndexCapsResponse> {
|
||||
|
||||
@Override
|
||||
protected GetRollupIndexCapsResponse createTestInstance() {
|
||||
return new GetRollupIndexCapsResponse(indices);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void toXContent(GetRollupIndexCapsResponse response, XContentBuilder builder) throws IOException {
|
||||
builder.startObject();
|
||||
for (Map.Entry<String, RollableIndexCaps> entry : response.getJobs().entrySet()) {
|
||||
entry.getValue().toXContent(builder, null);
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GetRollupIndexCapsResponse fromXContent(XContentParser parser) throws IOException {
|
||||
return GetRollupIndexCapsResponse.fromXContent(parser);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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.rollup;
|
||||
|
||||
import org.elasticsearch.client.rollup.job.config.DateHistogramGroupConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.GroupConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.HistogramGroupConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.MetricConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.RollupJobConfig;
|
||||
import org.elasticsearch.client.rollup.job.config.RollupJobConfigTests;
|
||||
import org.elasticsearch.client.rollup.job.config.TermsGroupConfig;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.HistogramAggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.elasticsearch.test.AbstractXContentTestCase.xContentTester;
|
||||
|
||||
abstract class RollupCapsResponseTestCase<T> extends ESTestCase {
|
||||
|
||||
protected Map<String, RollableIndexCaps> indices;
|
||||
|
||||
protected abstract T createTestInstance();
|
||||
|
||||
protected abstract void toXContent(T response, XContentBuilder builder) throws IOException;
|
||||
|
||||
protected abstract T fromXContent(XContentParser parser) throws IOException;
|
||||
|
||||
public void testFromXContent() throws IOException {
|
||||
xContentTester(
|
||||
this::createParser,
|
||||
this::createTestInstance,
|
||||
this::toXContent,
|
||||
this::fromXContent)
|
||||
.supportsUnknownFields(false)
|
||||
.randomFieldsExcludeFilter(field ->
|
||||
field.endsWith("job_id"))
|
||||
.test();
|
||||
}
|
||||
|
||||
@Before
|
||||
private void setupIndices() throws IOException {
|
||||
int numIndices = randomIntBetween(1,5);
|
||||
indices = new HashMap<>(numIndices);
|
||||
for (int i = 0; i < numIndices; i++) {
|
||||
String indexName = "index_" + randomAlphaOfLength(10);
|
||||
int numJobs = randomIntBetween(1,5);
|
||||
List<RollupJobCaps> jobs = new ArrayList<>(numJobs);
|
||||
for (int j = 0; j < numJobs; j++) {
|
||||
RollupJobConfig config = RollupJobConfigTests.randomRollupJobConfig(randomAlphaOfLength(10));
|
||||
jobs.add(new RollupJobCaps(config.getId(), config.getIndexPattern(),
|
||||
config.getRollupIndex(), createRollupFieldCaps(config)));
|
||||
}
|
||||
RollableIndexCaps cap = new RollableIndexCaps(indexName, jobs);
|
||||
indices.put(indexName, cap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifted from core's RollupJobCaps, so that we can test without having to include this actual logic in the request
|
||||
*/
|
||||
private static Map<String, RollupJobCaps.RollupFieldCaps> createRollupFieldCaps(final RollupJobConfig rollupJobConfig) {
|
||||
final Map<String, List<Map<String, Object>>> tempFieldCaps = new HashMap<>();
|
||||
|
||||
final GroupConfig groupConfig = rollupJobConfig.getGroupConfig();
|
||||
if (groupConfig != null) {
|
||||
// Create RollupFieldCaps for the date histogram
|
||||
final DateHistogramGroupConfig dateHistogram = groupConfig.getDateHistogram();
|
||||
final Map<String, Object> dateHistogramAggCap = new HashMap<>();
|
||||
dateHistogramAggCap.put("agg", DateHistogramAggregationBuilder.NAME);
|
||||
dateHistogramAggCap.put("interval", dateHistogram.getInterval().toString());
|
||||
if (dateHistogram.getDelay() != null) {
|
||||
dateHistogramAggCap.put("delay", dateHistogram.getDelay().toString());
|
||||
}
|
||||
dateHistogramAggCap.put("time_zone", dateHistogram.getTimeZone());
|
||||
|
||||
List<Map<String, Object>> dateAggCaps = tempFieldCaps.getOrDefault(dateHistogram.getField(), new ArrayList<>());
|
||||
dateAggCaps.add(dateHistogramAggCap);
|
||||
tempFieldCaps.put(dateHistogram.getField(), dateAggCaps);
|
||||
|
||||
// Create RollupFieldCaps for the histogram
|
||||
final HistogramGroupConfig histogram = groupConfig.getHistogram();
|
||||
if (histogram != null) {
|
||||
final Map<String, Object> histogramAggCap = new HashMap<>();
|
||||
histogramAggCap.put("agg", HistogramAggregationBuilder.NAME);
|
||||
histogramAggCap.put("interval", histogram.getInterval());
|
||||
Arrays.stream(rollupJobConfig.getGroupConfig().getHistogram().getFields()).forEach(field -> {
|
||||
List<Map<String, Object>> caps = tempFieldCaps.getOrDefault(field, new ArrayList<>());
|
||||
caps.add(histogramAggCap);
|
||||
tempFieldCaps.put(field, caps);
|
||||
});
|
||||
}
|
||||
|
||||
// Create RollupFieldCaps for the term
|
||||
final TermsGroupConfig terms = groupConfig.getTerms();
|
||||
if (terms != null) {
|
||||
final Map<String, Object> termsAggCap = singletonMap("agg", TermsAggregationBuilder.NAME);
|
||||
Arrays.stream(rollupJobConfig.getGroupConfig().getTerms().getFields()).forEach(field -> {
|
||||
List<Map<String, Object>> caps = tempFieldCaps.getOrDefault(field, new ArrayList<>());
|
||||
caps.add(termsAggCap);
|
||||
tempFieldCaps.put(field, caps);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Create RollupFieldCaps for the metrics
|
||||
final List<MetricConfig> metricsConfig = rollupJobConfig.getMetricsConfig();
|
||||
if (metricsConfig.size() > 0) {
|
||||
rollupJobConfig.getMetricsConfig().forEach(metricConfig -> {
|
||||
final List<Map<String, Object>> metrics = metricConfig.getMetrics().stream()
|
||||
.map(metric -> singletonMap("agg", (Object) metric))
|
||||
.collect(Collectors.toList());
|
||||
metrics.forEach(m -> {
|
||||
List<Map<String, Object>> caps = tempFieldCaps
|
||||
.getOrDefault(metricConfig.getField(), new ArrayList<>());
|
||||
caps.add(m);
|
||||
tempFieldCaps.put(metricConfig.getField(), caps);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(tempFieldCaps.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey,
|
||||
e -> new RollupJobCaps.RollupFieldCaps(e.getValue()))));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
--
|
||||
:api: rollup-get-rollup-index-caps
|
||||
:request: GetRollupIndexCapsRequest
|
||||
:response: GetRollupIndexCapsResponse
|
||||
--
|
||||
|
||||
[id="{upid}-x-pack-{api}"]
|
||||
=== Get Rollup Index Capabilities API
|
||||
|
||||
The Get Rollup Index Capabilities API allows the user to determine if a concrete index or index pattern contains
|
||||
stored rollup jobs and data. If it contains data stored from rollup jobs, the capabilities of those jobs
|
||||
are returned. The API accepts a `GetRollupIndexCapsRequest` object as a request and returns a `GetRollupIndexCapsResponse`.
|
||||
|
||||
[id="{upid}-x-pack-{api}-request"]
|
||||
==== Get Rollup Index Capabilities Request
|
||||
|
||||
A +{request}+ requires a single parameter: the target index or index pattern (e.g. `rollup-foo`):
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests-file}[x-pack-{api}-request]
|
||||
--------------------------------------------------
|
||||
|
||||
[id="{upid}-x-pack-{api}-execution"]
|
||||
==== Execution
|
||||
|
||||
The Get Rollup Index Capabilities API can be executed through a `RollupClient`
|
||||
instance. Such instance can be retrieved from a `RestHighLevelClient`
|
||||
using the `rollup()` method:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests-file}[x-pack-{api}-execute]
|
||||
--------------------------------------------------
|
||||
|
||||
[id="{upid}-x-pack-{api}-response"]
|
||||
==== Response
|
||||
|
||||
The returned +{response}+ holds lists and maps of values which correspond to the capabilities
|
||||
of the rollup index/index pattern (what jobs are stored in the index, their capabilities, what
|
||||
aggregations are available, etc). Because multiple jobs can be stored in one index, the
|
||||
response may include several jobs with different configurations.
|
||||
|
||||
The capabilities are essentially the same as the original job configuration, just presented in a different
|
||||
manner. For example, if we had created a job with the following config:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests-file}[x-pack-{api}-setup]
|
||||
--------------------------------------------------
|
||||
|
||||
The +{response}+ object would contain the same information, laid out in a slightly different manner:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests-file}[x-pack-{api}-response]
|
||||
--------------------------------------------------
|
||||
|
||||
[id="{upid}-x-pack-{api}-async"]
|
||||
==== Asynchronous Execution
|
||||
|
||||
This request can be executed asynchronously:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests-file}[x-pack-{api}-execute-async]
|
||||
--------------------------------------------------
|
||||
<1> The +{request}+ to execute and the `ActionListener` to use when
|
||||
the execution completes
|
||||
|
||||
The asynchronous method does not block and returns immediately. Once it is
|
||||
completed the `ActionListener` is called back using the `onResponse` method
|
||||
if the execution successfully completed or using the `onFailure` method if
|
||||
it failed.
|
||||
|
||||
A typical listener for +{response}+ looks like:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests-file}[x-pack-{api}-execute-listener]
|
||||
--------------------------------------------------
|
||||
<1> Called when the execution is successfully completed. The response is
|
||||
provided as an argument
|
||||
<2> Called in case of failure. The raised exception is provided as an argument
|
|
@ -311,12 +311,14 @@ The Java High Level REST Client supports the following Rollup APIs:
|
|||
* <<{upid}-rollup-delete-job>>
|
||||
* <<java-rest-high-x-pack-rollup-get-job>>
|
||||
* <<{upid}-x-pack-rollup-get-rollup-caps>>
|
||||
* <<{upid}-x-pack-rollup-get-rollup-index-caps>>
|
||||
|
||||
include::rollup/put_job.asciidoc[]
|
||||
include::rollup/start_job.asciidoc[]
|
||||
include::rollup/delete_job.asciidoc[]
|
||||
include::rollup/get_job.asciidoc[]
|
||||
include::rollup/get_rollup_caps.asciidoc[]
|
||||
include::rollup/get_rollup_index_caps.asciidoc[]
|
||||
|
||||
== Security APIs
|
||||
|
||||
|
|
Loading…
Reference in New Issue