/*
* 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.action.admin.indices.alias;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.arrayWithSize;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
public class AliasActionsTests extends ESTestCase {
public void testValidate() {
AliasActions.Type type = randomFrom(AliasActions.Type.values());
if (type == AliasActions.Type.REMOVE_INDEX) {
Exception e = expectThrows(IllegalArgumentException.class, () -> new AliasActions(type).validate());
assertEquals("One of [index] or [indices] is required", e.getMessage());
} else {
Exception e = expectThrows(IllegalArgumentException.class,
() -> new AliasActions(type).alias(randomAlphaOfLength(5)).validate());
assertEquals("One of [index] or [indices] is required", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> new AliasActions(type).index(randomAlphaOfLength(5)).validate());
assertEquals("One of [alias] or [aliases] is required", e.getMessage());
}
}
public void testEmptyIndex() {
Exception e = expectThrows(IllegalArgumentException.class,
() -> new AliasActions(randomFrom(AliasActions.Type.values())).index(null));
assertEquals("[index] can't be empty string", e.getMessage());
e = expectThrows(IllegalArgumentException.class,
() -> new AliasActions(randomFrom(AliasActions.Type.values())).index(""));
assertEquals("[index] can't be empty string", e.getMessage());
e = expectThrows(IllegalArgumentException.class,
() -> new AliasActions(randomFrom(AliasActions.Type.values())).indices((String[]) null));
assertEquals("[indices] can't be empty", e.getMessage());
e = expectThrows(IllegalArgumentException.class,
() -> new AliasActions(randomFrom(AliasActions.Type.values())).indices(new String[0]));
assertEquals("[indices] can't be empty", e.getMessage());
e = expectThrows(IllegalArgumentException.class,
() -> new AliasActions(randomFrom(AliasActions.Type.values())).indices("test", null));
assertEquals("[indices] can't contain empty string", e.getMessage());
e = expectThrows(IllegalArgumentException.class,
() -> new AliasActions(randomFrom(AliasActions.Type.values())).indices("test", ""));
assertEquals("[indices] can't contain empty string", e.getMessage());
}
public void testEmptyAlias() {
AliasActions.Type type = randomValueOtherThan(AliasActions.Type.REMOVE_INDEX, () -> randomFrom(AliasActions.Type.values()));
Exception e = expectThrows(IllegalArgumentException.class, () -> new AliasActions(type).alias(null));
assertEquals("[alias] can't be empty string", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> new AliasActions(type).alias(""));
assertEquals("[alias] can't be empty string", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> new AliasActions(type).aliases((String[]) null));
assertEquals("[aliases] can't be empty", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> new AliasActions(type).aliases(new String[0]));
assertEquals("[aliases] can't be empty", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> new AliasActions(type).aliases("test", null));
assertEquals("[aliases] can't contain empty string", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> new AliasActions(type).aliases("test", ""));
assertEquals("[aliases] can't contain empty string", e.getMessage());
}
public void testBadOptionsInNonIndex() {
AliasActions action = randomBoolean() ? AliasActions.remove() : AliasActions.removeIndex();
Exception e = expectThrows(IllegalArgumentException.class, () -> action.routing("test"));
assertEquals("[routing] is unsupported for [" + action.actionType() + "]", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> action.searchRouting("test"));
assertEquals("[search_routing] is unsupported for [" + action.actionType() + "]", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> action.indexRouting("test"));
assertEquals("[index_routing] is unsupported for [" + action.actionType() + "]", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> action.filter("test"));
assertEquals("[filter] is unsupported for [" + action.actionType() + "]", e.getMessage());
}
public void testParseAdd() throws IOException {
String[] indices = generateRandomStringArray(10, 5, false, false);
String[] aliases = generateRandomStringArray(10, 5, false, false);
Map<String, Object> filter = randomBoolean() ? randomMap(5) : null;
Object searchRouting = randomBoolean() ? randomRouting() : null;
Object indexRouting = randomBoolean() ? randomBoolean() ? searchRouting : randomRouting() : null;
XContentBuilder b = XContentBuilder.builder(randomFrom(XContentType.values()).xContent());
b.startObject(); {
b.startObject("add"); {
if (indices.length > 1 || randomBoolean()) {
b.array("indices", indices);
} else {
b.field("index", indices[0]);
}
if (aliases.length > 1 || randomBoolean()) {
b.array("aliases", aliases);
} else {
b.field("alias", aliases[0]);
}
if (filter != null) {
b.field("filter", filter);
}
if (searchRouting != null) {
if (searchRouting.equals(indexRouting)) {
b.field("routing", searchRouting);
} else {
b.field("search_routing", searchRouting);
}
}
if (indexRouting != null && false == indexRouting.equals(searchRouting)) {
b.field("index_routing", indexRouting);
}
}
b.endObject();
}
b.endObject();
b = shuffleXContent(b, "filter");
try (XContentParser parser = createParser(b)) {
AliasActions action = AliasActions.PARSER.apply(parser, null);
assertEquals(AliasActions.Type.ADD, action.actionType());
assertThat(action.indices(), equalTo(indices));
assertThat(action.aliases(), equalTo(aliases));
if (filter == null || filter.isEmpty()) {
assertNull(action.filter());
} else {
assertEquals(XContentFactory.contentBuilder(XContentType.JSON).map(filter).string(), action.filter());
}
assertEquals(Objects.toString(searchRouting, null), action.searchRouting());
assertEquals(Objects.toString(indexRouting, null), action.indexRouting());
}
}
public void testParseAddDefaultRouting() throws IOException {
String index = randomAlphaOfLength(5);
String alias = randomAlphaOfLength(5);
Object searchRouting = randomRouting();
Object indexRouting = randomRouting();
XContentBuilder b = XContentBuilder.builder(randomFrom(XContentType.values()).xContent());
b.startObject(); {
b.startObject("add"); {
b.field("index", index);
b.field("alias", alias);
if (randomBoolean()) {
b.field("routing", searchRouting);
b.field("index_routing", indexRouting);
} else {
b.field("search_routing", searchRouting);
b.field("routing", indexRouting);
}
}
b.endObject();
}
b.endObject();
b = shuffleXContent(b);
try (XContentParser parser = createParser(b)) {
AliasActions action = AliasActions.PARSER.apply(parser, null);
assertEquals(AliasActions.Type.ADD, action.actionType());
assertThat(action.indices(), arrayContaining(index));
assertThat(action.aliases(), arrayContaining(alias));
assertEquals(searchRouting.toString(), action.searchRouting());
assertEquals(indexRouting.toString(), action.indexRouting());
}
}
public void testParseRemove() throws IOException {
String[] indices = generateRandomStringArray(10, 5, false, false);
String[] aliases = generateRandomStringArray(10, 5, false, false);
XContentBuilder b = XContentBuilder.builder(randomFrom(XContentType.values()).xContent());
b.startObject(); {
b.startObject("remove"); {
if (indices.length > 1 || randomBoolean()) {
b.array("indices", indices);
} else {
b.field("index", indices[0]);
}
if (aliases.length > 1 || randomBoolean()) {
b.array("aliases", aliases);
} else {
b.field("alias", aliases[0]);
}
}
b.endObject();
}
b.endObject();
b = shuffleXContent(b);
try (XContentParser parser = createParser(b)) {
AliasActions action = AliasActions.PARSER.apply(parser, null);
assertEquals(AliasActions.Type.REMOVE, action.actionType());
assertThat(action.indices(), equalTo(indices));
assertThat(action.aliases(), equalTo(aliases));
}
}
public void testParseRemoveIndex() throws IOException {
String[] indices = randomBoolean() ? new String[] {randomAlphaOfLength(5)} : generateRandomStringArray(10, 5, false, false);
XContentBuilder b = XContentBuilder.builder(randomFrom(XContentType.values()).xContent());
b.startObject(); {
b.startObject("remove_index"); {
if (indices.length > 1 || randomBoolean()) {
b.array("indices", indices);
} else {
b.field("index", indices[0]);
}
}
b.endObject();
}
b.endObject();
b = shuffleXContent(b);
try (XContentParser parser = createParser(b)) {
AliasActions action = AliasActions.PARSER.apply(parser, null);
assertEquals(AliasActions.Type.REMOVE_INDEX, action.actionType());
assertArrayEquals(indices, action.indices());
assertThat(action.aliases(), arrayWithSize(0));
}
}
public void testParseIndexAndIndicesThrowsError() throws IOException {
XContentBuilder b = XContentBuilder.builder(randomFrom(XContentType.values()).xContent());
b.startObject(); {
b.startObject(randomFrom("add", "remove")); {
b.field("index", randomAlphaOfLength(5));
b.array("indices", generateRandomStringArray(10, 5, false, false));
b.field("alias", randomAlphaOfLength(5));
}
b.endObject();
}
b.endObject();
try (XContentParser parser = createParser(b)) {
Exception e = expectThrows(ParsingException.class, () -> AliasActions.PARSER.apply(parser, null));
assertThat(e.getCause().getCause(), instanceOf(IllegalArgumentException.class));
assertEquals("Only one of [index] and [indices] is supported", e.getCause().getCause().getMessage());
}
}
public void testParseAliasAndAliasesThrowsError() throws IOException {
XContentBuilder b = XContentBuilder.builder(randomFrom(XContentType.values()).xContent());
b.startObject(); {
b.startObject(randomFrom("add", "remove")); {
b.field("index", randomAlphaOfLength(5));
b.field("alias", randomAlphaOfLength(5));
b.array("aliases", generateRandomStringArray(10, 5, false, false));
}
b.endObject();
}
b.endObject();
try (XContentParser parser = createParser(b)) {
Exception e = expectThrows(ParsingException.class, () -> AliasActions.PARSER.apply(parser, null));
assertThat(e.getCause().getCause(), instanceOf(IllegalArgumentException.class));
assertEquals("Only one of [alias] and [aliases] is supported", e.getCause().getCause().getMessage());
}
}
public void testRoundTrip() throws IOException {
AliasActions action = new AliasActions(randomFrom(AliasActions.Type.values()));
if (randomBoolean()) {
action.index(randomAlphaOfLength(5));
} else {
action.indices(generateRandomStringArray(5, 5, false, false));
}
if (action.actionType() != AliasActions.Type.REMOVE_INDEX) {
if (randomBoolean()) {
action.alias(randomAlphaOfLength(5));
} else {
action.aliases(generateRandomStringArray(5, 5, false, false));
}
}
if (action.actionType() == AliasActions.Type.ADD) {
if (randomBoolean()) {
action.filter(randomAlphaOfLength(10));
}
if (randomBoolean()) {
if (randomBoolean()) {
action.routing(randomAlphaOfLength(5));
} else {
action.searchRouting(randomAlphaOfLength(5));
action.indexRouting(randomAlphaOfLength(5));
}
}
}
try (BytesStreamOutput out = new BytesStreamOutput()) {
action.writeTo(out);
try (StreamInput in = out.bytes().streamInput()) {
AliasActions read = new AliasActions(in);
assertEquals(action, read);
}
}
}
private Map<String, Object> randomMap(int maxDepth) {
int members = between(0, 5);
Map<String, Object> result = new HashMap<>(members);
for (int i = 0; i < members; i++) {
Object value;
switch (between(0, 3)) {
case 0:
if (maxDepth > 0) {
value = randomMap(maxDepth - 1);
} else {
value = randomAlphaOfLength(5);
}
break;
case 1:
value = randomAlphaOfLength(5);
break;
case 2:
value = randomBoolean();
break;
case 3:
value = randomLong();
break;
default:
throw new UnsupportedOperationException();
}
result.put(randomAlphaOfLength(5), value);
}
return result;
}
private Object randomRouting() {
return randomBoolean() ? randomAlphaOfLength(5) : randomInt();
}
}