* 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:
parent
2c77c0df65
commit
c3dee628c7
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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\"}}}";
|
||||
|
|
Loading…
Reference in New Issue