Skip to content

Commit

Permalink
Expose 'features' option in Get Index API (#83083)
Browse files Browse the repository at this point in the history
  • Loading branch information
danhermann authored Jan 27, 2022
1 parent 836d9bc commit 4ad7814
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 3 deletions.
6 changes: 6 additions & 0 deletions docs/changelog/83083.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 83083
summary: Expose 'features' option in Get Index API
area: Indices APIs
type: enhancement
issues:
- 82948
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@
"default":"open",
"description":"Whether wildcard expressions should get expanded to open or closed indices (default: open)"
},
"features":{
"type":"enum",
"options":[
"aliases",
"mappings",
"settings"
],
"default":"aliases,mappings,settings",
"description":"Return only information on specified index features"
},
"flat_settings":{
"type":"boolean",
"description":"Return settings in flat format (default: false)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,18 @@ setup:
catch: bad_request
indices.get:
index: _foo

---
"Should return only selected features":
- skip:
version: " - 8.0.99"
reason: "features option added in 8.1.0"

- do:
indices.get:
index: test_index
features: aliases,settings

- is_true: test_index.aliases
- is_true: test_index.settings
- match: { test_index.mappings: {}}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.util.ArrayUtils;
import org.elasticsearch.rest.RestRequest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

/**
* A request to retrieve information about an index.
Expand Down Expand Up @@ -50,9 +56,33 @@ public static Feature fromId(byte id) {
}
return FEATURES[id];
}

public static Feature[] fromRequest(RestRequest request) {
if (request.hasParam("features")) {
String[] featureNames = request.param("features").split(",");
Set<Feature> features = new HashSet<>();
List<String> invalidFeatures = new ArrayList<>();
for (int k = 0; k < featureNames.length; k++) {
try {
features.add(Feature.valueOf(featureNames[k].toUpperCase(Locale.ROOT)));
} catch (IllegalArgumentException e) {
invalidFeatures.add(featureNames[k]);
}
}
if (invalidFeatures.size() > 0) {
throw new IllegalArgumentException(
String.format(Locale.ROOT, "Invalid features specified [%s]", String.join(",", invalidFeatures))
);
} else {
return features.toArray(Feature[]::new);
}
} else {
return DEFAULT_FEATURES;
}
}
}

private static final Feature[] DEFAULT_FEATURES = new Feature[] { Feature.ALIASES, Feature.MAPPINGS, Feature.SETTINGS };
static final Feature[] DEFAULT_FEATURES = new Feature[] { Feature.ALIASES, Feature.MAPPINGS, Feature.SETTINGS };
private Feature[] features = DEFAULT_FEATURES;
private boolean humanReadable = false;
private transient boolean includeDefaults = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
getIndexRequest.masterNodeTimeout(request.paramAsTime("master_timeout", getIndexRequest.masterNodeTimeout()));
getIndexRequest.humanReadable(request.paramAsBoolean("human", false));
getIndexRequest.includeDefaults(request.paramAsBoolean("include_defaults", false));
getIndexRequest.features(GetIndexRequest.Feature.fromRequest(request));
return channel -> client.admin().indices().getIndex(getIndexRequest, new RestToXContentListener<>(channel));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.action.admin.indices.get;

import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestRequestTests;
import org.elasticsearch.test.ESTestCase;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;

public class GetIndexRequestTests extends ESTestCase {

public void testFeaturesFromRequest() {
int numFeatures = randomIntBetween(1, GetIndexRequest.DEFAULT_FEATURES.length);
List<String> featureNames = new ArrayList<>();
List<GetIndexRequest.Feature> expectedFeatures = new ArrayList<>();
for (int k = 0; k < numFeatures; k++) {
GetIndexRequest.Feature feature = randomValueOtherThanMany(
f -> featureNames.contains(f.name()),
() -> randomFrom(GetIndexRequest.DEFAULT_FEATURES)
);
featureNames.add(feature.name());
expectedFeatures.add(feature);
}

RestRequest request = RestRequestTests.contentRestRequest("", Map.of("features", String.join(",", featureNames)));
GetIndexRequest.Feature[] featureArray = GetIndexRequest.Feature.fromRequest(request);
assertThat(featureArray, arrayContainingInAnyOrder(expectedFeatures.toArray(GetIndexRequest.Feature[]::new)));
}

public void testDuplicateFeatures() {
int numFeatures = randomIntBetween(1, 5);
GetIndexRequest.Feature feature = randomFrom(GetIndexRequest.DEFAULT_FEATURES);
List<String> featureList = new ArrayList<>();
for (int k = 0; k < numFeatures; k++) {
featureList.add(feature.name());
}
RestRequest request = RestRequestTests.contentRestRequest("", Map.of("features", String.join(",", featureList)));
GetIndexRequest.Feature[] features = GetIndexRequest.Feature.fromRequest(request);
assertThat(features.length, equalTo(1));
assertThat(features[0], equalTo(feature));
}

public void testMissingFeatures() {
RestRequest request = RestRequestTests.contentRestRequest("", Map.of());
GetIndexRequest.Feature[] features = GetIndexRequest.Feature.fromRequest(request);
assertThat(features, arrayContainingInAnyOrder(GetIndexRequest.DEFAULT_FEATURES));
}

public void testInvalidFeatures() {
int numFeatures = randomIntBetween(1, 4);
List<String> invalidFeatures = new ArrayList<>();
for (int k = 0; k < numFeatures; k++) {
invalidFeatures.add(randomAlphaOfLength(5));
}

RestRequest request = RestRequestTests.contentRestRequest("", Map.of("features", String.join(",", invalidFeatures)));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> GetIndexRequest.Feature.fromRequest(request));
assertThat(
e.getMessage(),
containsString(String.format(Locale.ROOT, "Invalid features specified [%s]", String.join(",", invalidFeatures)))
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public void testRequiredContent() {
assertEquals("unknown content type", e.getMessage());
}

private static RestRequest contentRestRequest(String content, Map<String, String> params) {
public static RestRequest contentRestRequest(String content, Map<String, String> params) {
Map<String, List<String>> headers = new HashMap<>();
headers.put("Content-Type", Collections.singletonList("application/json"));
return contentRestRequest(content, params, headers);
Expand All @@ -250,7 +250,7 @@ private static RestRequest contentRestRequest(String content, Map<String, String
return new ContentRestRequest(builder.build());
}

private static final class ContentRestRequest extends RestRequest {
public static final class ContentRestRequest extends RestRequest {

private final RestRequest restRequest;

Expand Down

0 comments on commit 4ad7814

Please sign in to comment.