/*
* 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.cluster.metadata;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.VersionUtils;
import java.util.Arrays;
import java.util.Collection;
import static java.util.Collections.singletonList;
import static org.hamcrest.Matchers.contains;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anySetOf;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class MetaDataIndexAliasesServiceTests extends ESTestCase {
private final AliasValidator aliasValidator = new AliasValidator(Settings.EMPTY);
private final MetaDataDeleteIndexService deleteIndexService = mock(MetaDataDeleteIndexService.class);
private final MetaDataIndexAliasesService service = new MetaDataIndexAliasesService(Settings.EMPTY, null, null, aliasValidator,
deleteIndexService, xContentRegistry());
public MetaDataIndexAliasesServiceTests() {
// Mock any deletes so we don't need to worry about how MetaDataDeleteIndexService does its job
when(deleteIndexService.deleteIndices(any(ClusterState.class), anySetOf(Index.class))).then(i -> {
ClusterState state = (ClusterState) i.getArguments()[0];
@SuppressWarnings("unchecked")
Collection<Index> indices = (Collection<Index>) i.getArguments()[1];
MetaData.Builder meta = MetaData.builder(state.metaData());
for (Index index : indices) {
assertTrue("index now found", state.metaData().hasConcreteIndex(index.getName()));
meta.remove(index.getName()); // We only think about metadata for this test. Not routing or any other fun stuff.
}
return ClusterState.builder(state).metaData(meta).build();
});
}
public void testAddAndRemove() {
// Create a state with a single index
String index = randomAlphaOfLength(5);
ClusterState before = createIndex(ClusterState.builder(ClusterName.DEFAULT).build(), index);
// Add an alias to it
ClusterState after = service.innerExecute(before, singletonList(new AliasAction.Add(index, "test", null, null, null)));
AliasOrIndex alias = after.metaData().getAliasAndIndexLookup().get("test");
assertNotNull(alias);
assertTrue(alias.isAlias());
assertThat(alias.getIndices(), contains(after.metaData().index(index)));
// Remove the alias from it while adding another one
before = after;
after = service.innerExecute(before, Arrays.asList(
new AliasAction.Remove(index, "test"),
new AliasAction.Add(index, "test_2", null, null, null)));
assertNull(after.metaData().getAliasAndIndexLookup().get("test"));
alias = after.metaData().getAliasAndIndexLookup().get("test_2");
assertNotNull(alias);
assertTrue(alias.isAlias());
assertThat(alias.getIndices(), contains(after.metaData().index(index)));
// Now just remove on its own
before = after;
after = service.innerExecute(before, singletonList(new AliasAction.Remove(index, "test_2")));
assertNull(after.metaData().getAliasAndIndexLookup().get("test"));
assertNull(after.metaData().getAliasAndIndexLookup().get("test_2"));
}
public void testSwapIndexWithAlias() {
// Create "test" and "test_2"
ClusterState before = createIndex(ClusterState.builder(ClusterName.DEFAULT).build(), "test");
before = createIndex(before, "test_2");
// Now remove "test" and add an alias to "test" to "test_2" in one go
ClusterState after = service.innerExecute(before, Arrays.asList(
new AliasAction.Add("test_2", "test", null, null, null),
new AliasAction.RemoveIndex("test")));
AliasOrIndex alias = after.metaData().getAliasAndIndexLookup().get("test");
assertNotNull(alias);
assertTrue(alias.isAlias());
assertThat(alias.getIndices(), contains(after.metaData().index("test_2")));
}
public void testAddAliasToRemovedIndex() {
// Create "test"
ClusterState before = createIndex(ClusterState.builder(ClusterName.DEFAULT).build(), "test");
// Attempt to add an alias to "test" at the same time as we remove it
IndexNotFoundException e = expectThrows(IndexNotFoundException.class, () -> service.innerExecute(before, Arrays.asList(
new AliasAction.Add("test", "alias", null, null, null),
new AliasAction.RemoveIndex("test"))));
assertEquals("test", e.getIndex().getName());
}
public void testRemoveIndexTwice() {
// Create "test"
ClusterState before = createIndex(ClusterState.builder(ClusterName.DEFAULT).build(), "test");
// Try to remove an index twice. This should just remove the index once....
ClusterState after = service.innerExecute(before, Arrays.asList(
new AliasAction.RemoveIndex("test"),
new AliasAction.RemoveIndex("test")));
assertNull(after.metaData().getAliasAndIndexLookup().get("test"));
}
private ClusterState createIndex(ClusterState state, String index) {
IndexMetaData indexMetaData = IndexMetaData.builder(index)
.settings(Settings.builder().put("index.version.created", VersionUtils.randomVersion(random())))
.numberOfShards(1)
.numberOfReplicas(1)
.build();
return ClusterState.builder(state)
.metaData(MetaData.builder(state.metaData()).put(indexMetaData, false))
.build();
}
}