Remove PROTO-based custom cluster state components

Switches custom cluster state components from PROTO-based de-serialization to named objects based de-serialization

Original commit: elastic/x-pack-elasticsearch@e1be8597ee
This commit is contained in:
Igor Motov 2016-12-19 11:53:48 -05:00
parent 505ed14c97
commit 576a512ef2
13 changed files with 128 additions and 60 deletions

View File

@ -6,6 +6,8 @@
package org.elasticsearch.license;
import org.elasticsearch.cluster.AbstractDiffable;
import org.elasticsearch.cluster.AbstractNamedDiffable;
import org.elasticsearch.cluster.NamedDiff;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@ -20,7 +22,7 @@ import java.util.EnumSet;
/**
* Contains metadata about registered licenses
*/
class LicensesMetaData extends AbstractDiffable<MetaData.Custom> implements MetaData.Custom,
class LicensesMetaData extends AbstractNamedDiffable<MetaData.Custom> implements MetaData.Custom,
TribeService.MergableCustomMetaData<LicensesMetaData> {
public static final String TYPE = "licenses";
@ -45,8 +47,6 @@ class LicensesMetaData extends AbstractDiffable<MetaData.Custom> implements Meta
.expiryDate(0)
.build();
public static final LicensesMetaData PROTO = new LicensesMetaData(null);
private License license;
public LicensesMetaData(License license) {
@ -79,7 +79,7 @@ class LicensesMetaData extends AbstractDiffable<MetaData.Custom> implements Meta
}
@Override
public String type() {
public String getWriteableName() {
return TYPE;
}
@ -88,8 +88,7 @@ class LicensesMetaData extends AbstractDiffable<MetaData.Custom> implements Meta
return EnumSet.of(MetaData.XContentContext.GATEWAY);
}
@Override
public LicensesMetaData fromXContent(XContentParser parser) throws IOException {
public static LicensesMetaData fromXContent(XContentParser parser) throws IOException {
License license = LICENSE_TOMBSTONE;
XContentParser.Token token;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
@ -132,13 +131,16 @@ class LicensesMetaData extends AbstractDiffable<MetaData.Custom> implements Meta
}
}
@Override
public LicensesMetaData readFrom(StreamInput streamInput) throws IOException {
License license = LICENSE_TOMBSTONE;
public LicensesMetaData(StreamInput streamInput) throws IOException {
if (streamInput.readBoolean()) {
license = License.readLicense(streamInput);
} else {
license = LICENSE_TOMBSTONE;
}
return new LicensesMetaData(license);
}
public static NamedDiff<MetaData.Custom> readDiffFrom(StreamInput streamInput) throws IOException {
return readDiffFrom(MetaData.Custom.class, TYPE, streamInput);
}
@Override

View File

@ -7,12 +7,17 @@ package org.elasticsearch.license;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.cluster.NamedDiff;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.plugins.ActionPlugin;
import org.elasticsearch.rest.RestHandler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@ -28,16 +33,20 @@ public class Licensing implements ActionPlugin {
protected final boolean isTransportClient;
private final boolean isTribeNode;
static {
// we have to make sure we don't override the prototype, if we already
// registered. This causes class cast exceptions while casting license
// meta data on tribe node, as the registration happens for every tribe
// client nodes and the tribe node itself
if (MetaData.lookupPrototype(LicensesMetaData.TYPE) == null) {
MetaData.registerPrototype(LicensesMetaData.TYPE, LicensesMetaData.PROTO);
}
public List<NamedWriteableRegistry.Entry> getNamedWriteables() {
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
entries.add(new NamedWriteableRegistry.Entry(MetaData.Custom.class, LicensesMetaData.TYPE, LicensesMetaData::new));
entries.add(new NamedWriteableRegistry.Entry(NamedDiff.class, LicensesMetaData.TYPE, LicensesMetaData::readDiffFrom));
return entries;
}
public List<NamedXContentRegistry.Entry> getNamedXContent() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>();
// Metadata
entries.add(new NamedXContentRegistry.Entry(MetaData.Custom.class, new ParseField(LicensesMetaData.TYPE),
LicensesMetaData::fromXContent));
return entries;
}
public Licensing(Settings settings) {
this.settings = settings;
isTransportClient = transportClientMode(settings);

View File

@ -408,12 +408,23 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
@Override
public List<NamedWriteableRegistry.Entry> getNamedWriteables() {
return Arrays.asList(
new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, SECURITY, SecurityFeatureSet.Usage::new),
new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, WATCHER, WatcherFeatureSet.Usage::new),
new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, MONITORING, MonitoringFeatureSet.Usage::new),
new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, GRAPH, GraphFeatureSet.Usage::new)
);
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
entries.add(new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, SECURITY, SecurityFeatureSet.Usage::new));
entries.add(new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, WATCHER, WatcherFeatureSet.Usage::new));
entries.add(new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, MONITORING, MonitoringFeatureSet.Usage::new));
entries.add(new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, GRAPH, GraphFeatureSet.Usage::new));
entries.addAll(watcher.getNamedWriteables());
entries.addAll(licensing.getNamedWriteables());
return entries;
}
@Override
public List<NamedXContentRegistry.Entry> getNamedXContent() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>();
entries.addAll(watcher.getNamedXContent());
entries.addAll(licensing.getNamedXContent());
return entries;
}
public void onIndexModule(IndexModule module) {

View File

@ -9,12 +9,15 @@ import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.NamedDiff;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.logging.LoggerMessageFormat;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.regex.Regex;
@ -187,8 +190,19 @@ public class Watcher implements ActionPlugin, ScriptPlugin {
private static final Logger logger = Loggers.getLogger(XPackPlugin.class);
static {
MetaData.registerPrototype(WatcherMetaData.TYPE, WatcherMetaData.PROTO);
public List<NamedWriteableRegistry.Entry> getNamedWriteables() {
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
entries.add(new NamedWriteableRegistry.Entry(MetaData.Custom.class, WatcherMetaData.TYPE, WatcherMetaData::new));
entries.add(new NamedWriteableRegistry.Entry(NamedDiff.class, WatcherMetaData.TYPE, WatcherMetaData::readDiffFrom));
return entries;
}
public List<NamedXContentRegistry.Entry> getNamedXContent() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>();
// Metadata
entries.add(new NamedXContentRegistry.Entry(MetaData.Custom.class, new ParseField(WatcherMetaData.TYPE),
WatcherMetaData::fromXContent));
return entries;
}
protected final Settings settings;

View File

@ -6,6 +6,8 @@
package org.elasticsearch.xpack.watcher;
import org.elasticsearch.cluster.AbstractDiffable;
import org.elasticsearch.cluster.AbstractNamedDiffable;
import org.elasticsearch.cluster.NamedDiff;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParseFieldMatcher;
@ -17,10 +19,9 @@ import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.EnumSet;
public class WatcherMetaData extends AbstractDiffable<MetaData.Custom> implements MetaData.Custom {
public class WatcherMetaData extends AbstractNamedDiffable<MetaData.Custom> implements MetaData.Custom {
public static final String TYPE = "watcher";
public static final WatcherMetaData PROTO = new WatcherMetaData(false);
private final boolean manuallyStopped;
@ -33,7 +34,7 @@ public class WatcherMetaData extends AbstractDiffable<MetaData.Custom> implement
}
@Override
public String type() {
public String getWriteableName() {
return TYPE;
}
@ -42,9 +43,12 @@ public class WatcherMetaData extends AbstractDiffable<MetaData.Custom> implement
return EnumSet.of(MetaData.XContentContext.GATEWAY);
}
@Override
public MetaData.Custom readFrom(StreamInput streamInput) throws IOException {
return new WatcherMetaData(streamInput.readBoolean());
public WatcherMetaData(StreamInput streamInput) throws IOException {
this(streamInput.readBoolean());
}
public static NamedDiff<MetaData.Custom> readDiffFrom(StreamInput streamInput) throws IOException {
return readDiffFrom(MetaData.Custom.class, TYPE, streamInput);
}
@Override
@ -52,8 +56,7 @@ public class WatcherMetaData extends AbstractDiffable<MetaData.Custom> implement
streamOutput.writeBoolean(manuallyStopped);
}
@Override
public MetaData.Custom fromXContent(XContentParser parser) throws IOException {
public static MetaData.Custom fromXContent(XContentParser parser) throws IOException {
XContentParser.Token token;
Boolean manuallyStopped = null;
String currentFieldName = null;

View File

@ -260,11 +260,6 @@ public class WatcherXContentParser implements XContentParser {
return parser.getTokenLocation();
}
@Override
public boolean isClosed() {
return parser.isClosed();
}
@Override
public <T> T namedObject(Class<T> categoryClass, String name, Object context) throws IOException {
return parser.namedObject(categoryClass, name, context);
@ -275,6 +270,11 @@ public class WatcherXContentParser implements XContentParser {
return parser.getXContentRegistry();
}
@Override
public boolean isClosed() {
return parser.isClosed();
}
@Override
public void close() throws ElasticsearchException {
parser.close();

View File

@ -127,7 +127,7 @@ public class WatcherStatsResponse extends ActionResponse implements ToXContent {
queuedWatches.add(new QueuedWatch(in));
}
}
watcherMetaData = (WatcherMetaData) WatcherMetaData.PROTO.readFrom(in);
watcherMetaData = new WatcherMetaData(in);
}
@Override

View File

@ -35,8 +35,9 @@ public class LicenseTribeTests extends TribeTransportTestCase {
}
@Override
protected void verifyActionOnTribeNode(Client tribeClient) {
failAction(tribeClient, GetLicenseAction.INSTANCE);
protected void verifyActionOnTribeNode(Client tribeClient) throws Exception {
// The get licence action should work, but everything else should fail
tribeClient.execute(GetLicenseAction.INSTANCE, new GetLicenseRequest()).get();
failAction(tribeClient, PutLicenseAction.INSTANCE);
failAction(tribeClient, DeleteLicenseAction.INSTANCE);
}

View File

@ -5,11 +5,13 @@
*/
package org.elasticsearch.license;
import org.elasticsearch.cluster.ClusterModule;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.metadata.RepositoriesMetaData;
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.ToXContent.Params;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -19,6 +21,8 @@ import org.elasticsearch.test.ESTestCase;
import java.util.Collections;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
@ -46,11 +50,11 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
RepositoriesMetaData repositoriesMetaData = new RepositoriesMetaData(repositoryMetaData);
final MetaData.Builder metaDataBuilder = MetaData.builder();
if (randomBoolean()) { // random order of insertion
metaDataBuilder.putCustom(licensesMetaData.type(), licensesMetaData);
metaDataBuilder.putCustom(repositoriesMetaData.type(), repositoriesMetaData);
metaDataBuilder.putCustom(licensesMetaData.getWriteableName(), licensesMetaData);
metaDataBuilder.putCustom(repositoriesMetaData.getWriteableName(), repositoriesMetaData);
} else {
metaDataBuilder.putCustom(repositoriesMetaData.type(), repositoriesMetaData);
metaDataBuilder.putCustom(licensesMetaData.type(), licensesMetaData);
metaDataBuilder.putCustom(repositoriesMetaData.getWriteableName(), repositoriesMetaData);
metaDataBuilder.putCustom(licensesMetaData.getWriteableName(), licensesMetaData);
}
// serialize metadata
XContentBuilder builder = XContentFactory.jsonBuilder();
@ -61,8 +65,8 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
// deserialize metadata again
MetaData metaData = MetaData.Builder.fromXContent(createParser(builder));
// check that custom metadata still present
assertThat(metaData.custom(licensesMetaData.type()), notNullValue());
assertThat(metaData.custom(repositoriesMetaData.type()), notNullValue());
assertThat(metaData.custom(licensesMetaData.getWriteableName()), notNullValue());
assertThat(metaData.custom(repositoriesMetaData.getWriteableName()), notNullValue());
}
public void testXContentSerializationOneTrial() throws Exception {
@ -99,9 +103,17 @@ public class LicensesMetaDataSerializationTests extends ESTestCase {
private static LicensesMetaData getLicensesMetaDataFromXContent(XContentParser parser) throws Exception {
parser.nextToken(); // consume null
parser.nextToken(); // consume "licenses"
LicensesMetaData licensesMetaDataFromXContent = LicensesMetaData.PROTO.fromXContent(parser);
LicensesMetaData licensesMetaDataFromXContent = LicensesMetaData.fromXContent(parser);
parser.nextToken(); // consume endObject
assertThat(parser.nextToken(), nullValue());
return licensesMetaDataFromXContent;
}
@Override
protected NamedXContentRegistry xContentRegistry() {
return new NamedXContentRegistry(Stream.concat(
new Licensing(Settings.EMPTY).getNamedXContent().stream(),
ClusterModule.getNamedXWriteables().stream()
).collect(Collectors.toList()));
}
}

View File

@ -136,11 +136,15 @@ public abstract class TribeTransportTestCase extends ESIntegTestCase {
.put(tribe2Defaults.build())
.put(NetworkModule.HTTP_ENABLED.getKey(), false)
.put(internalCluster().getDefaultSettings())
.put(XPackSettings.SECURITY_ENABLED.getKey(), false) // otherwise it conflicts with mock transport
.put("tribe.t1." + XPackSettings.SECURITY_ENABLED.getKey(), false)
.put("tribe.t2." + XPackSettings.SECURITY_ENABLED.getKey(), false)
.put("node.name", "tribe_node") // make sure we can identify threads from this node
.put("transport.type", MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME)
.build();
final List<Class<? extends Plugin>> mockPlugins = Arrays.asList(TestZenDiscovery.TestPlugin.class, MockTcpTransportPlugin.class);
final List<Class<? extends Plugin>> mockPlugins = Arrays.asList(TestZenDiscovery.TestPlugin.class, MockTcpTransportPlugin.class,
XPackPlugin.class);
final Node tribeNode = new MockNode(merged, mockPlugins).start();
Client tribeClient = tribeNode.client();
@ -189,7 +193,7 @@ public abstract class TribeTransportTestCase extends ESIntegTestCase {
/**
* Verify transport action behaviour on tribe node
*/
protected abstract void verifyActionOnTribeNode(Client tribeClient);
protected abstract void verifyActionOnTribeNode(Client tribeClient) throws Exception;
protected void failAction(Client client, Action action) {
try {

View File

@ -510,7 +510,7 @@ public class HttpExporterIT extends MonitoringIntegTestCase {
doc.setClusterUUID(internalCluster().getClusterName());
doc.setTimestamp(System.currentTimeMillis());
doc.setSourceNode(new DiscoveryNode("id", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT));
doc.setClusterState(ClusterState.PROTO);
doc.setClusterState(ClusterState.EMPTY_STATE);
doc.setStatus(ClusterHealthStatus.GREEN);
return doc;
}

View File

@ -210,7 +210,7 @@ public class LocalExporterTests extends MonitoringIntegTestCase {
doc.setClusterUUID(internalCluster().getClusterName());
doc.setTimestamp(System.currentTimeMillis());
doc.setSourceNode(new DiscoveryNode("id", buildNewFakeTransportAddress(), emptyMap(), emptySet(), Version.CURRENT));
doc.setClusterState(ClusterState.PROTO);
doc.setClusterState(ClusterState.EMPTY_STATE);
doc.setStatus(ClusterHealthStatus.GREEN);
return doc;
}

View File

@ -5,10 +5,12 @@
*/
package org.elasticsearch.xpack.watcher;
import org.elasticsearch.cluster.ClusterModule;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.metadata.RepositoriesMetaData;
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
@ -16,6 +18,8 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.ESTestCase;
import java.util.Collections;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
@ -43,11 +47,11 @@ public class WatcherMetaDataSerializationTests extends ESTestCase {
RepositoriesMetaData repositoriesMetaData = new RepositoriesMetaData(repositoryMetaData);
final MetaData.Builder metaDataBuilder = MetaData.builder();
if (randomBoolean()) { // random order of insertion
metaDataBuilder.putCustom(watcherMetaData.type(), watcherMetaData);
metaDataBuilder.putCustom(repositoriesMetaData.type(), repositoriesMetaData);
metaDataBuilder.putCustom(watcherMetaData.getWriteableName(), watcherMetaData);
metaDataBuilder.putCustom(repositoriesMetaData.getWriteableName(), repositoriesMetaData);
} else {
metaDataBuilder.putCustom(repositoriesMetaData.type(), repositoriesMetaData);
metaDataBuilder.putCustom(watcherMetaData.type(), watcherMetaData);
metaDataBuilder.putCustom(repositoriesMetaData.getWriteableName(), repositoriesMetaData);
metaDataBuilder.putCustom(watcherMetaData.getWriteableName(), watcherMetaData);
}
// serialize metadata
XContentBuilder builder = XContentFactory.jsonBuilder();
@ -59,17 +63,25 @@ public class WatcherMetaDataSerializationTests extends ESTestCase {
// deserialize metadata again
MetaData metaData = MetaData.Builder.fromXContent(createParser(builder));
// check that custom metadata still present
assertThat(metaData.custom(watcherMetaData.type()), notNullValue());
assertThat(metaData.custom(repositoriesMetaData.type()), notNullValue());
assertThat(metaData.custom(watcherMetaData.getWriteableName()), notNullValue());
assertThat(metaData.custom(repositoriesMetaData.getWriteableName()), notNullValue());
}
private static WatcherMetaData getWatcherMetaDataFromXContent(XContentParser parser) throws Exception {
parser.nextToken(); // consume null
parser.nextToken(); // consume "watcher"
WatcherMetaData watcherMetaDataFromXContent = (WatcherMetaData)WatcherMetaData.PROTO.fromXContent(parser);
WatcherMetaData watcherMetaDataFromXContent = (WatcherMetaData)WatcherMetaData.fromXContent(parser);
parser.nextToken(); // consume endObject
assertThat(parser.nextToken(), nullValue());
return watcherMetaDataFromXContent;
}
@Override
protected NamedXContentRegistry xContentRegistry() {
return new NamedXContentRegistry(Stream.concat(
new Watcher(Settings.EMPTY).getNamedXContent().stream(),
ClusterModule.getNamedXWriteables().stream()
).collect(Collectors.toList()));
}
}