Skip to content

Commit

Permalink
Fix Get Alias API handling of hidden indices with visible aliases (#5…
Browse files Browse the repository at this point in the history
…3147)

This commit changes the Get Aliases API to include hidden indices by
default - this is slightly different from other APIs, but is necessary
to make this API work intuitively.
  • Loading branch information
gwbrown committed Mar 7, 2020
1 parent 28354f5 commit 69cddcb
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class GetAliasesRequest extends MasterNodeReadRequest<GetAliasesRequest>

private String[] indices = Strings.EMPTY_ARRAY;
private String[] aliases = Strings.EMPTY_ARRAY;
private IndicesOptions indicesOptions = IndicesOptions.strictExpand();
private IndicesOptions indicesOptions = IndicesOptions.strictExpandHidden();
private String[] originalAliases = Strings.EMPTY_ARRAY;

public GetAliasesRequest(String... aliases) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ public enum Option {
EnumSet.of(WildcardStates.OPEN, WildcardStates.CLOSED, WildcardStates.HIDDEN));
public static final IndicesOptions STRICT_EXPAND_OPEN_CLOSED =
new IndicesOptions(EnumSet.of(Option.ALLOW_NO_INDICES), EnumSet.of(WildcardStates.OPEN, WildcardStates.CLOSED));
public static final IndicesOptions STRICT_EXPAND_OPEN_CLOSED_HIDDEN =
new IndicesOptions(EnumSet.of(Option.ALLOW_NO_INDICES),
EnumSet.of(WildcardStates.OPEN, WildcardStates.CLOSED, WildcardStates.HIDDEN));
public static final IndicesOptions STRICT_EXPAND_OPEN_FORBID_CLOSED =
new IndicesOptions(EnumSet.of(Option.ALLOW_NO_INDICES, Option.FORBID_CLOSED_INDICES), EnumSet.of(WildcardStates.OPEN));
public static final IndicesOptions STRICT_EXPAND_OPEN_HIDDEN_FORBID_CLOSED =
Expand Down Expand Up @@ -406,6 +409,14 @@ public static IndicesOptions strictExpand() {
return STRICT_EXPAND_OPEN_CLOSED;
}

/**
* @return indices option that requires every specified index to exist, expands wildcards to both open and closed indices, includes
* hidden indices, and allows that no indices are resolved from wildcard expressions (not returning an error).
*/
public static IndicesOptions strictExpandHidden() {
return STRICT_EXPAND_OPEN_CLOSED_HIDDEN;
}

/**
* @return indices option that requires each specified index or alias to exist, doesn't expand wildcards and
* throws error if any of the aliases resolves to multiple indices
Expand Down
65 changes: 65 additions & 0 deletions server/src/test/java/org/elasticsearch/index/HiddenIndexIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

package org.elasticsearch.index;

import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequestBuilder;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.search.SearchResponse;
Expand All @@ -36,7 +39,10 @@

import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;

public class HiddenIndexIT extends ESIntegTestCase {

Expand Down Expand Up @@ -135,4 +141,63 @@ public void testNonGlobalTemplateCanMakeIndexHidden() {
GetSettingsResponse getSettingsResponse = client().admin().indices().prepareGetSettings("my_hidden_pattern1").get();
assertThat(getSettingsResponse.getSetting("my_hidden_pattern1", "index.hidden"), is("true"));
}

public void testAliasesForHiddenIndices() {
final String hiddenIndex = "hidden-index";
final String visibleAlias = "alias-visible";
final String hiddenAlias = "alias-hidden";
final String dotHiddenAlias = ".alias-hidden";

assertAcked(client().admin().indices().prepareCreate(hiddenIndex)
.setSettings(Settings.builder().put("index.hidden", true).build())
.get());

assertAcked(admin().indices().prepareAliases()
.addAliasAction(IndicesAliasesRequest.AliasActions.add().index(hiddenIndex).alias(visibleAlias)));

// The index should be returned here when queried by name or by wildcard because the alias is visible
final GetAliasesRequestBuilder req = client().admin().indices().prepareGetAliases(visibleAlias);
GetAliasesResponse response = req.get();
assertThat(response.getAliases().get(hiddenIndex), hasSize(1));
assertThat(response.getAliases().get(hiddenIndex).get(0).alias(), equalTo(visibleAlias));
assertThat(response.getAliases().get(hiddenIndex).get(0).isHidden(), nullValue());

response = client().admin().indices().prepareGetAliases("alias*").get();
assertThat(response.getAliases().get(hiddenIndex), hasSize(1));
assertThat(response.getAliases().get(hiddenIndex).get(0).alias(), equalTo(visibleAlias));
assertThat(response.getAliases().get(hiddenIndex).get(0).isHidden(), nullValue());

// Now try with a hidden alias
assertAcked(admin().indices().prepareAliases()
.addAliasAction(IndicesAliasesRequest.AliasActions.remove().index(hiddenIndex).alias(visibleAlias))
.addAliasAction(IndicesAliasesRequest.AliasActions.add().index(hiddenIndex).alias(hiddenAlias).isHidden(true)));

// Querying by name directly should get the right result
response = client().admin().indices().prepareGetAliases(hiddenAlias).get();
assertThat(response.getAliases().get(hiddenIndex), hasSize(1));
assertThat(response.getAliases().get(hiddenIndex).get(0).alias(), equalTo(hiddenAlias));
assertThat(response.getAliases().get(hiddenIndex).get(0).isHidden(), equalTo(true));

// querying by wildcard should get the right result because the indices options include hidden by default
response = client().admin().indices().prepareGetAliases("alias*").get();
assertThat(response.getAliases().get(hiddenIndex), hasSize(1));
assertThat(response.getAliases().get(hiddenIndex).get(0).alias(), equalTo(hiddenAlias));
assertThat(response.getAliases().get(hiddenIndex).get(0).isHidden(), equalTo(true));

// But we should get no results if we specify indices options that don't include hidden
response = client().admin().indices().prepareGetAliases("alias*")
.setIndicesOptions(IndicesOptions.strictExpandOpen()).get();
assertThat(response.getAliases().get(hiddenIndex), nullValue());

// Now try with a hidden alias that starts with a dot
assertAcked(admin().indices().prepareAliases()
.addAliasAction(IndicesAliasesRequest.AliasActions.remove().index(hiddenIndex).alias(hiddenAlias))
.addAliasAction(IndicesAliasesRequest.AliasActions.add().index(hiddenIndex).alias(dotHiddenAlias).isHidden(true)));

// Check that querying by dot-prefixed pattern returns the alias
response = client().admin().indices().prepareGetAliases(".alias*").get();
assertThat(response.getAliases().get(hiddenIndex), hasSize(1));
assertThat(response.getAliases().get(hiddenIndex).get(0).alias(), equalTo(dotHiddenAlias));
assertThat(response.getAliases().get(hiddenIndex).get(0).isHidden(), equalTo(true));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@

import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesAction;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesAction;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequestBuilder;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse;
import org.elasticsearch.action.admin.indices.create.CreateIndexAction;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.rest.action.admin.indices.AliasesNotFoundException;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.hamcrest.Matchers;
import org.junit.Before;

import java.util.Collections;
Expand All @@ -28,6 +31,8 @@
import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.nullValue;

public class IndexAliasesTests extends SecurityIntegTestCase {

Expand Down Expand Up @@ -590,6 +595,61 @@ public void testRemoveIndex() {
assertAliases(client().admin().indices().prepareGetAliases().setAliases("*"), "bogus_index_1", "bogus_alias_1", "bogus_alias_2");
}

public void testAliasesForHiddenIndices() {
final String hiddenIndex = "test_hidden";
final String visibleAlias = "alias_visible";
final String hiddenAlias = "alias_hidden";

final Map<String, String> createHeaders = Collections.singletonMap(
BASIC_AUTH_HEADER, basicAuthHeaderValue("all_on_test", new SecureString("test123".toCharArray())));
final Client createClient = client(createHeaders);

final Map<String, String> aliasHeaders = Collections.singletonMap(
BASIC_AUTH_HEADER, basicAuthHeaderValue("aliases_only", new SecureString("test123".toCharArray())));
final Client aliasesClient = client(aliasHeaders);

assertAcked(createClient.admin().indices().prepareCreate(hiddenIndex)
.setSettings(Settings.builder().put("index.hidden", true).build())
.get());

assertAcked(aliasesClient.admin().indices().prepareAliases()
.addAliasAction(IndicesAliasesRequest.AliasActions.add().index(hiddenIndex).alias(visibleAlias)));

// The index should be returned here when queried by name or by wildcard because the alias is visible
final GetAliasesRequestBuilder req = aliasesClient.admin().indices().prepareGetAliases(visibleAlias);
GetAliasesResponse response = req.get();
assertThat(response.getAliases().get(hiddenIndex), hasSize(1));
assertThat(response.getAliases().get(hiddenIndex).get(0).alias(), Matchers.equalTo(visibleAlias));
assertThat(response.getAliases().get(hiddenIndex).get(0).isHidden(), nullValue());

response = client().admin().indices().prepareGetAliases("alias*").get();
assertThat(response.getAliases().get(hiddenIndex), hasSize(1));
assertThat(response.getAliases().get(hiddenIndex).get(0).alias(), Matchers.equalTo(visibleAlias));
assertThat(response.getAliases().get(hiddenIndex).get(0).isHidden(), nullValue());

// Now try with a hidden alias
assertAcked(aliasesClient.admin().indices().prepareAliases()
.addAliasAction(IndicesAliasesRequest.AliasActions.remove().index(hiddenIndex).alias(visibleAlias))
.addAliasAction(IndicesAliasesRequest.AliasActions.add().index(hiddenIndex).alias(hiddenAlias).isHidden(true)));

// Querying by name directly should get the right result
response = aliasesClient.admin().indices().prepareGetAliases(hiddenAlias).get();
assertThat(response.getAliases().get(hiddenIndex), hasSize(1));
assertThat(response.getAliases().get(hiddenIndex).get(0).alias(), Matchers.equalTo(hiddenAlias));
assertThat(response.getAliases().get(hiddenIndex).get(0).isHidden(), Matchers.equalTo(true));

// querying by wildcard should get the right result because the indices options include hidden by default
response = aliasesClient.admin().indices().prepareGetAliases("alias*").get();
assertThat(response.getAliases().get(hiddenIndex), hasSize(1));
assertThat(response.getAliases().get(hiddenIndex).get(0).alias(), Matchers.equalTo(hiddenAlias));
assertThat(response.getAliases().get(hiddenIndex).get(0).isHidden(), Matchers.equalTo(true));

// But we should get no results if we specify indices options that don't include hidden
response = aliasesClient.admin().indices().prepareGetAliases("alias*")
.setIndicesOptions(IndicesOptions.strictExpandOpen()).get();
assertThat(response.getAliases().get(hiddenIndex), nullValue());
}

private static Client client(final Map<String, String> headers) {
// it should not matter what client we send the request to, but let's pin all requests to a specific node
final Client client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -983,11 +983,12 @@ public void testResolveAllGetAliasesRequest() {
request.aliases("alias1");
final List<String> authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//the union of all resolved indices and aliases gets returned
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed", "alias1"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed"};
//the union of all resolved indices and aliases gets returned, including hidden indices as Get Aliases includes hidden by default
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed", "alias1",
"hidden-open", "hidden-closed", ".hidden-open", ".hidden-closed"};
assertSameValues(indices, expectedIndices);
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed", "hidden-open",
"hidden-closed", ".hidden-open", ".hidden-closed"};
//_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContainingInAnyOrder(replacedIndices));
assertThat(request.aliases(), arrayContainingInAnyOrder("alias1"));
Expand Down Expand Up @@ -1063,8 +1064,9 @@ public void testResolveAllAliasesGetAliasesRequest() {
}
final List<String> authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//the union of all resolved indices and aliases gets returned
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed"};
//the union of all resolved indices and aliases gets returned, including hidden indices as Get Aliases includes hidden by default
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed", "hidden-open",
"hidden-closed", ".hidden-open", ".hidden-closed"};
assertSameValues(indices, expectedIndices);
//_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
Expand All @@ -1078,11 +1080,14 @@ public void testResolveAllAndExplicitAliasesGetAliasesRequest() {
}
final List<String> authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//the union of all resolved indices and aliases gets returned
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed", "explicit"};
//the union of all resolved indices and aliases gets returned, including hidden indices as Get Aliases includes hidden by default
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed", "explicit",
"hidden-open", "hidden-closed", ".hidden-open", ".hidden-closed"};
logger.info("indices: {}", indices);
assertSameValues(indices, expectedIndices);
//_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContainingInAnyOrder("bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed"));
assertThat(request.indices(), arrayContainingInAnyOrder("bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed",
"hidden-open", "hidden-closed", ".hidden-open", ".hidden-closed"));
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar", "foobarfoo", "explicit"));
}

Expand All @@ -1093,8 +1098,9 @@ public void testResolveAllAndWildcardsAliasesGetAliasesRequest() {
}
final List<String> authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//the union of all resolved indices and aliases gets returned
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed"};
//the union of all resolved indices and aliases gets returned, including hidden indices as Get Aliases includes hidden by default
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foobarfoo", "foofoo", "foofoo-closed", "hidden-open",
"hidden-closed", ".hidden-open", ".hidden-closed"};
assertSameValues(indices, expectedIndices);
//_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
Expand Down Expand Up @@ -1134,10 +1140,13 @@ public void testResolveAliasesExclusionWildcardsGetAliasesRequest() {
//union of all resolved indices and aliases gets returned, based on what user is authorized for
//note that the index side will end up containing matching aliases too, which is fine, as es core would do
//the same and resolve those aliases to their corresponding concrete indices (which we let core do)
String[] expectedIndices = new String[]{"bar", "bar-closed", "foobarfoo", "foofoo", "foofoo-closed", "foofoobar"};
//also includes hidden indices as Get Aliases includes hidden by default
String[] expectedIndices = new String[]{"bar", "bar-closed", "foobarfoo", "foofoo", "foofoo-closed", "foofoobar", "hidden-open",
"hidden-closed", ".hidden-open", ".hidden-closed"};
assertSameValues(indices, expectedIndices);
//alias foofoobar on both sides, that's fine, es core would do the same, same as above
assertThat(request.indices(), arrayContainingInAnyOrder("bar", "bar-closed", "foobarfoo", "foofoo", "foofoo-closed", "foofoobar"));
assertThat(request.indices(), arrayContainingInAnyOrder("bar", "bar-closed", "foobarfoo", "foofoo", "foofoo-closed", "foofoobar",
"hidden-open", "hidden-closed", ".hidden-open", ".hidden-closed"));
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar"));
}

Expand Down

0 comments on commit 69cddcb

Please sign in to comment.