[7.x] Add IndexTemplateV2 to MetaData (#53753) (#53827)

* Add IndexTemplateV2 to MetaData (#53753)

* Add IndexTemplateV2 to MetaData

This adds the `IndexTemplateV2` and `IndexTemplateV2Metadata` class to be used for the new
implementation of index templates. The new metadata is stored as a `MetaData.Custom` implementation.

Relates to #53101

* Add ITV2Metadata unit tests

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>

* Update min supported version constant

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Lee Hinman 2020-03-19 15:04:00 -06:00 committed by GitHub
parent 2c77c0df65
commit c3dee628c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 679 additions and 0 deletions

View File

@ -25,6 +25,7 @@ import org.elasticsearch.cluster.action.shard.ShardStateAction;
import org.elasticsearch.cluster.metadata.ComponentTemplateMetadata;
import org.elasticsearch.cluster.metadata.IndexGraveyard;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.IndexTemplateV2Metadata;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.metadata.MetaDataDeleteIndexService;
import org.elasticsearch.cluster.metadata.MetaDataIndexAliasesService;
@ -133,6 +134,8 @@ public class ClusterModule extends AbstractModule {
PersistentTasksCustomMetaData::readDiffFrom);
registerMetaDataCustom(entries, ComponentTemplateMetadata.TYPE, ComponentTemplateMetadata::new,
ComponentTemplateMetadata::readDiffFrom);
registerMetaDataCustom(entries, IndexTemplateV2Metadata.TYPE, IndexTemplateV2Metadata::new,
IndexTemplateV2Metadata::readDiffFrom);
// Task Status (not Diffable)
entries.add(new Entry(Task.Status.class, PersistentTasksNodeService.Status.NAME, PersistentTasksNodeService.Status::new));
return entries;
@ -182,6 +185,8 @@ public class ClusterModule extends AbstractModule {
PersistentTasksCustomMetaData::fromXContent));
entries.add(new NamedXContentRegistry.Entry(MetaData.Custom.class, new ParseField(ComponentTemplateMetadata.TYPE),
ComponentTemplateMetadata::fromXContent));
entries.add(new NamedXContentRegistry.Entry(MetaData.Custom.class, new ParseField(IndexTemplateV2Metadata.TYPE),
IndexTemplateV2Metadata::fromXContent));
return entries;
}

View File

@ -0,0 +1,201 @@
/*
* 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.AbstractDiffable;
import org.elasticsearch.cluster.Diff;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* An index template is comprised of a set of index patterns, an optional template, and a list of
* ids corresponding to component templates that should be composed in order when creating a new
* index.
*/
public class IndexTemplateV2 extends AbstractDiffable<IndexTemplateV2> implements ToXContentObject {
private static final ParseField INDEX_PATTERNS = new ParseField("index_patterns");
private static final ParseField TEMPLATE = new ParseField("template");
private static final ParseField PRIORITY = new ParseField("priority");
private static final ParseField COMPOSED_OF = new ParseField("composed_of");
private static final ParseField VERSION = new ParseField("version");
private static final ParseField METADATA = new ParseField("_meta");
@SuppressWarnings("unchecked")
private static final ConstructingObjectParser<IndexTemplateV2, Void> PARSER = new ConstructingObjectParser<>("index_template", false,
a -> new IndexTemplateV2((List<String>) a[0],
(Template) a[1],
(List<String>) a[2],
(Long) a[3],
(Long) a[4],
(Map<String, Object>) a[5]));
static {
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), INDEX_PATTERNS);
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), Template.PARSER, TEMPLATE);
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), COMPOSED_OF);
PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), PRIORITY);
PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), VERSION);
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), (p, c) -> p.map(), METADATA);
}
private final List<String> indexPatterns;
@Nullable
private final Template template;
@Nullable
private final List<String> componentTemplates;
@Nullable
private final Long priority;
@Nullable
private final Long version;
@Nullable
private final Map<String, Object> metadata;
static Diff<IndexTemplateV2> readITV2DiffFrom(StreamInput in) throws IOException {
return AbstractDiffable.readDiffFrom(IndexTemplateV2::new, in);
}
public static IndexTemplateV2 parse(XContentParser parser) throws IOException {
return PARSER.parse(parser, null);
}
public IndexTemplateV2(List<String> indexPatterns, @Nullable Template template, @Nullable List<String> componentTemplates,
@Nullable Long priority, @Nullable Long version, @Nullable Map<String, Object> metadata) {
this.indexPatterns = indexPatterns;
this.template = template;
this.componentTemplates = componentTemplates;
this.priority = priority;
this.version = version;
this.metadata = metadata;
}
public IndexTemplateV2(StreamInput in) throws IOException {
this.indexPatterns = in.readStringList();
if (in.readBoolean()) {
this.template = new Template(in);
} else {
this.template = null;
}
this.componentTemplates = in.readOptionalStringList();
this.priority = in.readOptionalVLong();
this.version = in.readOptionalVLong();
this.metadata = in.readMap();
}
public List<String> indexPatterns() {
return indexPatterns;
}
public Template template() {
return template;
}
public List<String> composedOf() {
return componentTemplates;
}
public Long priority() {
return priority;
}
public Long version() {
return version;
}
public Map<String, Object> metadata() {
return metadata;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeStringCollection(this.indexPatterns);
if (this.template == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
this.template.writeTo(out);
}
out.writeOptionalStringCollection(this.componentTemplates);
out.writeOptionalVLong(this.priority);
out.writeOptionalVLong(this.version);
out.writeMap(this.metadata);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(INDEX_PATTERNS.getPreferredName(), this.indexPatterns);
if (this.template != null) {
builder.field(TEMPLATE.getPreferredName(), this.template);
}
if (this.componentTemplates != null) {
builder.field(COMPOSED_OF.getPreferredName(), this.componentTemplates);
}
if (this.priority != null) {
builder.field(PRIORITY.getPreferredName(), priority);
}
if (this.version != null) {
builder.field(VERSION.getPreferredName(), version);
}
if (this.metadata != null) {
builder.field(METADATA.getPreferredName(), metadata);
}
builder.endObject();
return builder;
}
@Override
public int hashCode() {
return Objects.hash(this.indexPatterns, this.template, this.componentTemplates, this.priority, this.version, this.metadata);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
IndexTemplateV2 other = (IndexTemplateV2) obj;
return Objects.equals(this.indexPatterns, other.indexPatterns) &&
Objects.equals(this.template, other.template) &&
Objects.equals(this.componentTemplates, other.componentTemplates) &&
Objects.equals(this.priority, other.priority) &&
Objects.equals(this.version, other.version) &&
Objects.equals(this.metadata, other.metadata);
}
@Override
public String toString() {
return Strings.toString(this);
}
}

View File

@ -0,0 +1,170 @@
/*
* 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.Version;
import org.elasticsearch.cluster.Diff;
import org.elasticsearch.cluster.DiffableUtils;
import org.elasticsearch.cluster.NamedDiff;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* The {@link IndexTemplateV2Metadata} class is a custom {@link MetaData.Custom} implementation that
* stores a map of ids to {@link IndexTemplateV2} templates.
*/
public class IndexTemplateV2Metadata implements MetaData.Custom {
public static final String TYPE = "index_template";
private static final ParseField INDEX_TEMPLATE = new ParseField("index_template");
@SuppressWarnings("unchecked")
private static final ConstructingObjectParser<IndexTemplateV2Metadata, Void> PARSER = new ConstructingObjectParser<>(TYPE, false,
a -> new IndexTemplateV2Metadata((Map<String, IndexTemplateV2>) a[0]));
static {
PARSER.declareObject(ConstructingObjectParser.constructorArg(), (p, c) -> {
Map<String, IndexTemplateV2> templates = new HashMap<>();
while (p.nextToken() != XContentParser.Token.END_OBJECT) {
String name = p.currentName();
templates.put(name, IndexTemplateV2.parse(p));
}
return templates;
}, INDEX_TEMPLATE);
}
private final Map<String, IndexTemplateV2> indexTemplates;
public IndexTemplateV2Metadata(Map<String, IndexTemplateV2> templates) {
this.indexTemplates = templates;
}
public IndexTemplateV2Metadata(StreamInput in) throws IOException {
this.indexTemplates = in.readMap(StreamInput::readString, IndexTemplateV2::new);
}
public static IndexTemplateV2Metadata fromXContent(XContentParser parser) throws IOException {
return PARSER.parse(parser, null);
}
public Map<String, IndexTemplateV2> indexTemplates() {
return indexTemplates;
}
@Override
public EnumSet<MetaData.XContentContext> context() {
return MetaData.ALL_CONTEXTS;
}
@Override
public Diff<MetaData.Custom> diff(MetaData.Custom before) {
return new IndexTemplateV2MetadataDiff((IndexTemplateV2Metadata) before, this);
}
public static NamedDiff<MetaData.Custom> readDiffFrom(StreamInput in) throws IOException {
return new IndexTemplateV2MetadataDiff(in);
}
@Override
public String getWriteableName() {
return TYPE;
}
@Override
public Version getMinimalSupportedVersion() {
return Version.V_7_7_0;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeMap(this.indexTemplates, StreamOutput::writeString, (outstream, val) -> val.writeTo(outstream));
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(INDEX_TEMPLATE.getPreferredName());
for (Map.Entry<String, IndexTemplateV2> template : indexTemplates.entrySet()) {
builder.field(template.getKey(), template.getValue());
}
builder.endObject();
return builder;
}
@Override
public int hashCode() {
return Objects.hash(this.indexTemplates);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
IndexTemplateV2Metadata other = (IndexTemplateV2Metadata) obj;
return Objects.equals(this.indexTemplates, other.indexTemplates);
}
@Override
public String toString() {
return Strings.toString(this);
}
static class IndexTemplateV2MetadataDiff implements NamedDiff<MetaData.Custom> {
final Diff<Map<String, IndexTemplateV2>> indexTemplateDiff;
IndexTemplateV2MetadataDiff(IndexTemplateV2Metadata before, IndexTemplateV2Metadata after) {
this.indexTemplateDiff = DiffableUtils.diff(before.indexTemplates, after.indexTemplates,
DiffableUtils.getStringKeySerializer());
}
IndexTemplateV2MetadataDiff(StreamInput in) throws IOException {
this.indexTemplateDiff = DiffableUtils.readJdkMapDiff(in, DiffableUtils.getStringKeySerializer(),
IndexTemplateV2::new, IndexTemplateV2::readITV2DiffFrom);
}
@Override
public MetaData.Custom apply(MetaData.Custom part) {
return new IndexTemplateV2Metadata(indexTemplateDiff.apply(((IndexTemplateV2Metadata) part).indexTemplates));
}
@Override
public void writeTo(StreamOutput out) throws IOException {
indexTemplateDiff.writeTo(out);
}
@Override
public String getWriteableName() {
return TYPE;
}
}
}

View File

@ -727,6 +727,12 @@ public class MetaData implements Iterable<IndexMetaData>, Diffable<MetaData>, To
.orElse(Collections.emptyMap());
}
public Map<String, IndexTemplateV2> templatesV2() {
return Optional.ofNullable((IndexTemplateV2Metadata) this.custom(IndexTemplateV2Metadata.TYPE))
.map(IndexTemplateV2Metadata::indexTemplates)
.orElse(Collections.emptyMap());
}
public ImmutableOpenMap<String, Custom> customs() {
return this.customs;
}
@ -1163,6 +1169,34 @@ public class MetaData implements Iterable<IndexMetaData>, Diffable<MetaData>, To
return this;
}
public Builder indexTemplates(Map<String, IndexTemplateV2> indexTemplates) {
this.customs.put(IndexTemplateV2Metadata.TYPE, new IndexTemplateV2Metadata(indexTemplates));
return this;
}
public Builder put(String name, IndexTemplateV2 indexTemplate) {
Objects.requireNonNull(indexTemplate, "it is invalid to add a null index template: " + name);
// ಠ_ಠ at ImmutableOpenMap
Map<String, IndexTemplateV2> existingTemplates =
Optional.ofNullable((IndexTemplateV2Metadata) this.customs.get(IndexTemplateV2Metadata.TYPE))
.map(itmd -> new HashMap<>(itmd.indexTemplates()))
.orElse(new HashMap<>());
existingTemplates.put(name, indexTemplate);
this.customs.put(IndexTemplateV2Metadata.TYPE, new IndexTemplateV2Metadata(existingTemplates));
return this;
}
public Builder removeIndexTemplate(String name) {
// ಠ_ಠ at ImmutableOpenMap
Map<String, IndexTemplateV2> existingTemplates =
Optional.ofNullable((IndexTemplateV2Metadata) this.customs.get(IndexTemplateV2Metadata.TYPE))
.map(itmd -> new HashMap<>(itmd.indexTemplates()))
.orElse(new HashMap<>());
existingTemplates.remove(name);
this.customs.put(IndexTemplateV2Metadata.TYPE, new IndexTemplateV2Metadata(existingTemplates));
return this;
}
public Custom getCustom(String type) {
return customs.get(type);
}

View File

@ -0,0 +1,58 @@
/*
* 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.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.test.AbstractNamedWriteableTestCase;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class IndexTemplateV2MetadataTests extends AbstractNamedWriteableTestCase<IndexTemplateV2Metadata> {
@Override
protected IndexTemplateV2Metadata createTestInstance() {
if (randomBoolean()) {
return new IndexTemplateV2Metadata(Collections.emptyMap());
}
Map<String, IndexTemplateV2> templates = new HashMap<>();
for (int i = 0; i < randomIntBetween(1, 5); i++) {
templates.put(randomAlphaOfLength(5), IndexTemplateV2Tests.randomInstance());
}
return new IndexTemplateV2Metadata(templates);
}
@Override
protected IndexTemplateV2Metadata mutateInstance(IndexTemplateV2Metadata instance) throws IOException {
return randomValueOtherThan(instance, this::createTestInstance);
}
@Override
protected NamedWriteableRegistry getNamedWriteableRegistry() {
return new NamedWriteableRegistry(Collections.singletonList(new NamedWriteableRegistry.Entry(IndexTemplateV2Metadata.class,
IndexTemplateV2Metadata.TYPE, IndexTemplateV2Metadata::new)));
}
@Override
protected Class<IndexTemplateV2Metadata> categoryClass() {
return IndexTemplateV2Metadata.class;
}
}

View File

@ -0,0 +1,188 @@
/*
* 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.Diff;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractDiffableSerializationTestCase;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class IndexTemplateV2Tests extends AbstractDiffableSerializationTestCase<IndexTemplateV2> {
@Override
protected IndexTemplateV2 makeTestChanges(IndexTemplateV2 testInstance) {
try {
return mutateInstance(testInstance);
} catch (IOException e) {
logger.error(e);
fail("mutating should not throw an exception, but got: " + e);
return null;
}
}
@Override
protected Writeable.Reader<Diff<IndexTemplateV2>> diffReader() {
return IndexTemplateV2::readITV2DiffFrom;
}
@Override
protected IndexTemplateV2 doParseInstance(XContentParser parser) throws IOException {
return IndexTemplateV2.parse(parser);
}
@Override
protected Writeable.Reader<IndexTemplateV2> instanceReader() {
return IndexTemplateV2::new;
}
@Override
protected IndexTemplateV2 createTestInstance() {
return randomInstance();
}
public static IndexTemplateV2 randomInstance() {
Settings settings = null;
CompressedXContent mappings = null;
Map<String, AliasMetaData> aliases = null;
Template template = null;
if (randomBoolean()) {
if (randomBoolean()) {
settings = randomSettings();
}
if (randomBoolean()) {
mappings = randomMappings();
}
if (randomBoolean()) {
aliases = randomAliases();
}
template = new Template(settings, mappings, aliases);
}
Map<String, Object> meta = null;
if (randomBoolean()) {
meta = randomMeta();
}
List<String> indexPatterns = randomList(1, 4, () -> randomAlphaOfLength(4));
List<String> componentTemplates = randomList(0, 10, () -> randomAlphaOfLength(5));
return new IndexTemplateV2(indexPatterns,
template,
componentTemplates,
randomBoolean() ? null : randomNonNegativeLong(),
randomBoolean() ? null : randomNonNegativeLong(),
meta);
}
private static Map<String, AliasMetaData> randomAliases() {
String aliasName = randomAlphaOfLength(5);
AliasMetaData aliasMeta = AliasMetaData.builder(aliasName)
.filter(Collections.singletonMap(randomAlphaOfLength(2), randomAlphaOfLength(2)))
.routing(randomBoolean() ? null : randomAlphaOfLength(3))
.isHidden(randomBoolean() ? null : randomBoolean())
.writeIndex(randomBoolean() ? null : randomBoolean())
.build();
return Collections.singletonMap(aliasName, aliasMeta);
}
private static CompressedXContent randomMappings() {
try {
return new CompressedXContent("{\"" + randomAlphaOfLength(3) + "\":\"" + randomAlphaOfLength(7) + "\"}");
} catch (IOException e) {
fail("got an IO exception creating fake mappings: " + e);
return null;
}
}
private static Settings randomSettings() {
return Settings.builder()
.put(randomAlphaOfLength(4), randomAlphaOfLength(10))
.build();
}
private static Map<String, Object> randomMeta() {
if (randomBoolean()) {
return Collections.singletonMap(randomAlphaOfLength(4), randomAlphaOfLength(4));
} else {
return Collections.singletonMap(randomAlphaOfLength(5),
Collections.singletonMap(randomAlphaOfLength(4), randomAlphaOfLength(4)));
}
}
@Override
protected IndexTemplateV2 mutateInstance(IndexTemplateV2 orig) throws IOException {
return mutateTemplate(orig);
}
public static IndexTemplateV2 mutateTemplate(IndexTemplateV2 orig) {
switch (randomIntBetween(0, 5)) {
case 0:
List<String> newIndexPatterns = randomValueOtherThan(orig.indexPatterns(),
() -> randomList(1, 4, () -> randomAlphaOfLength(4)));
return new IndexTemplateV2(newIndexPatterns, orig.template(), orig.composedOf(),
orig.priority(), orig.version(), orig.metadata());
case 1:
return new IndexTemplateV2(orig.indexPatterns(),
randomValueOtherThan(orig.template(), () -> new Template(randomSettings(), randomMappings(), randomAliases())),
orig.composedOf(),
orig.priority(),
orig.version(),
orig.metadata());
case 2:
List<String> newComposedOf = randomValueOtherThan(orig.composedOf(),
() -> randomList(0, 10, () -> randomAlphaOfLength(5)));
return new IndexTemplateV2(orig.indexPatterns(),
orig.template(),
newComposedOf,
orig.priority(),
orig.version(),
orig.metadata());
case 3:
return new IndexTemplateV2(orig.indexPatterns(),
orig.template(),
orig.composedOf(),
randomValueOtherThan(orig.priority(), ESTestCase::randomNonNegativeLong),
orig.version(),
orig.metadata());
case 4:
return new IndexTemplateV2(orig.indexPatterns(),
orig.template(),
orig.composedOf(),
orig.priority(),
randomValueOtherThan(orig.version(), ESTestCase::randomNonNegativeLong),
orig.metadata());
case 5:
return new IndexTemplateV2(orig.indexPatterns(),
orig.template(),
orig.composedOf(),
orig.priority(),
orig.version(),
randomValueOtherThan(orig.metadata(), IndexTemplateV2Tests::randomMeta));
default:
throw new IllegalStateException("illegal randomization branch");
}
}
}

View File

@ -972,6 +972,7 @@ public class MetaDataTests extends ESTestCase {
.indexGraveyard(IndexGraveyardTests.createRandom())
.version(randomNonNegativeLong())
.put("component_template_" + randomAlphaOfLength(3), ComponentTemplateTests.randomInstance())
.put("index_template_v2_" + randomAlphaOfLength(3), IndexTemplateV2Tests.randomInstance())
.build();
}
}

View File

@ -26,6 +26,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import static org.elasticsearch.cluster.metadata.AliasMetaData.newAliasMetaDataBuilder;
@ -128,6 +129,14 @@ public class ToAndFromJsonMetaDataTests extends ESTestCase {
new CompressedXContent("{\"baz\":\"eggplant\"}"),
Collections.singletonMap("alias", AliasMetaData.builder("alias").build())),
5L, Collections.singletonMap("my_meta", Collections.singletonMap("foo", "bar"))))
.put("index_templatev2", new IndexTemplateV2(Arrays.asList("foo", "bar*"),
new Template(Settings.builder().put("setting", "value").build(),
new CompressedXContent("{\"baz\":\"eggplant\"}"),
Collections.singletonMap("alias", AliasMetaData.builder("alias").build())),
Collections.singletonList("component_template"),
5L,
4L,
Collections.singletonMap("my_meta", Collections.singletonMap("potato", "chicken"))))
.put(IndexMetaData.builder("test12")
.settings(settings(Version.CURRENT)
.put("setting1", "value1")
@ -323,6 +332,19 @@ public class ToAndFromJsonMetaDataTests extends ESTestCase {
equalTo(new Template(Settings.builder().put("setting", "value").build(),
new CompressedXContent("{\"baz\":\"eggplant\"}"),
Collections.singletonMap("alias", AliasMetaData.builder("alias").build()))));
// index template v2
assertNotNull(parsedMetaData.templatesV2().get("index_templatev2"));
assertThat(parsedMetaData.templatesV2().get("index_templatev2").priority(), is(5L));
assertThat(parsedMetaData.templatesV2().get("index_templatev2").version(), is(4L));
assertThat(parsedMetaData.templatesV2().get("index_templatev2").indexPatterns(), is(Arrays.asList("foo", "bar*")));
assertThat(parsedMetaData.templatesV2().get("index_templatev2").composedOf(), is(Collections.singletonList("component_template")));
assertThat(parsedMetaData.templatesV2().get("index_templatev2").metadata(),
equalTo(Collections.singletonMap("my_meta", Collections.singletonMap("potato", "chicken"))));
assertThat(parsedMetaData.templatesV2().get("index_templatev2").template(),
equalTo(new Template(Settings.builder().put("setting", "value").build(),
new CompressedXContent("{\"baz\":\"eggplant\"}"),
Collections.singletonMap("alias", AliasMetaData.builder("alias").build()))));
}
private static final String MAPPING_SOURCE1 = "{\"mapping1\":{\"text1\":{\"type\":\"string\"}}}";