diff --git a/elasticsearch/x-pack/graph/src/main/java/org/elasticsearch/graph/GraphFeatureSet.java b/elasticsearch/x-pack/graph/src/main/java/org/elasticsearch/graph/GraphFeatureSet.java index ea0fdf18e7c..b83db912369 100644 --- a/elasticsearch/x-pack/graph/src/main/java/org/elasticsearch/graph/GraphFeatureSet.java +++ b/elasticsearch/x-pack/graph/src/main/java/org/elasticsearch/graph/GraphFeatureSet.java @@ -7,9 +7,14 @@ package org.elasticsearch.graph; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.xpack.XPackFeatureSet; +import java.io.IOException; + /** * */ @@ -19,9 +24,10 @@ public class GraphFeatureSet implements XPackFeatureSet { private final GraphLicensee licensee; @Inject - public GraphFeatureSet(Settings settings, @Nullable GraphLicensee licensee) { + public GraphFeatureSet(Settings settings, @Nullable GraphLicensee licensee, NamedWriteableRegistry namedWriteableRegistry) { this.enabled = Graph.enabled(settings); this.licensee = licensee; + namedWriteableRegistry.register(Usage.class, Usage.WRITEABLE_NAME, Usage::new); } @Override @@ -43,4 +49,36 @@ public class GraphFeatureSet implements XPackFeatureSet { public boolean enabled() { return enabled; } + + @Override + public Usage usage() { + return new Usage(available(), enabled()); + } + + static class Usage extends XPackFeatureSet.Usage { + + static final String WRITEABLE_NAME = writeableName(Graph.NAME); + + public Usage(StreamInput input) throws IOException { + super(input); + } + + public Usage(boolean available, boolean enabled) { + super(Graph.NAME, available, enabled); + } + + @Override + public String getWriteableName() { + return WRITEABLE_NAME; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject() + .field(Field.AVAILABLE, available) + .field(Field.ENABLED, enabled) + .endObject(); + + } + } } diff --git a/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/MonitoringFeatureSet.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/MonitoringFeatureSet.java index 03a4b61b7b8..9ba1777b806 100644 --- a/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/MonitoringFeatureSet.java +++ b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/MonitoringFeatureSet.java @@ -7,9 +7,19 @@ package org.elasticsearch.marvel; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.marvel.agent.exporter.Exporter; +import org.elasticsearch.marvel.agent.exporter.Exporters; +import org.elasticsearch.marvel.agent.exporter.http.HttpExporter; +import org.elasticsearch.marvel.agent.exporter.local.LocalExporter; import org.elasticsearch.xpack.XPackFeatureSet; +import java.io.IOException; + /** * */ @@ -17,11 +27,15 @@ public class MonitoringFeatureSet implements XPackFeatureSet { private final boolean enabled; private final MonitoringLicensee licensee; + private final Exporters exporters; @Inject - public MonitoringFeatureSet(Settings settings, @Nullable MonitoringLicensee licensee) { + public MonitoringFeatureSet(Settings settings, @Nullable MonitoringLicensee licensee, Exporters exporters, + NamedWriteableRegistry namedWriteableRegistry) { this.enabled = MonitoringSettings.ENABLED.get(settings); this.licensee = licensee; + this.exporters = exporters; + namedWriteableRegistry.register(Usage.class, Usage.WRITEABLE_NAME, Usage::new); } @Override @@ -43,4 +57,98 @@ public class MonitoringFeatureSet implements XPackFeatureSet { public boolean enabled() { return enabled; } + + @Override + public Usage usage() { + + int enabledLocalExporters = 0; + int enabledHttpExporters = 0; + int enabledUnknownExporters = 0; + for (Exporter exporter : exporters) { + if (exporter.config().enabled()) { + switch (exporter.type()) { + case LocalExporter.TYPE: + enabledLocalExporters++; + break; + case HttpExporter.TYPE: + enabledHttpExporters++; + break; + default: + enabledUnknownExporters++; + } + } + } + + return new Usage(available(), enabled(), enabledLocalExporters, enabledHttpExporters, enabledUnknownExporters); + } + + static class Usage extends XPackFeatureSet.Usage { + + private static String WRITEABLE_NAME = writeableName(Monitoring.NAME); + + private final int enabledLocalExporters; + private final int enabledHttpExporters; + private final int enabledUnknownExporters; + + public Usage(StreamInput in) throws IOException { + super(in); + this.enabledLocalExporters = in.readVInt(); + this.enabledHttpExporters = in.readVInt(); + this.enabledUnknownExporters = in.readVInt(); + } + + public Usage(boolean available, boolean enabled, int enabledLocalExporters, int enabledHttpExporters, int enabledUnknownExporters) { + super(Monitoring.NAME, available, enabled); + this.enabledLocalExporters = enabledLocalExporters; + this.enabledHttpExporters = enabledHttpExporters; + this.enabledUnknownExporters = enabledUnknownExporters; + } + + @Override + public boolean available() { + return available; + } + + @Override + public boolean enabled() { + return enabled; + } + + @Override + public String getWriteableName() { + return WRITEABLE_NAME; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + out.writeVInt(enabledLocalExporters); + out.writeVInt(enabledHttpExporters); + out.writeVInt(enabledUnknownExporters); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(Field.AVAILABLE, available); + builder.field(Field.ENABLED, enabled); + + builder.startObject(Field.ENABLED_EXPORTERS); + builder.field(Field.LOCAL, enabledLocalExporters); + builder.field(Field.HTTP, enabledHttpExporters); + if (enabledUnknownExporters > 0) { + builder.field(Field.UNKNOWN, enabledUnknownExporters); + } + builder.endObject(); + + return builder.endObject(); + } + + interface Field extends XPackFeatureSet.Usage.Field { + String ENABLED_EXPORTERS = "enabled_exporters"; + String LOCAL = "_local"; + String HTTP = "http"; + String UNKNOWN = "_unknown"; + } + } } diff --git a/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporter.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporter.java index 6bf3b09564f..bf91863cfc0 100644 --- a/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporter.java +++ b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporter.java @@ -41,6 +41,10 @@ public abstract class Exporter implements AutoCloseable { return config.name; } + public Config config() { + return config; + } + public boolean masterOnly() { return false; } diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/SecurityFeatureSet.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/SecurityFeatureSet.java index e36c17ddec6..6a53e72eb52 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/SecurityFeatureSet.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/SecurityFeatureSet.java @@ -7,9 +7,15 @@ package org.elasticsearch.shield; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.marvel.Monitoring; import org.elasticsearch.xpack.XPackFeatureSet; +import java.io.IOException; + /** * */ @@ -19,9 +25,11 @@ public class SecurityFeatureSet implements XPackFeatureSet { private final SecurityLicenseState licenseState; @Inject - public SecurityFeatureSet(Settings settings, @Nullable SecurityLicenseState licenseState) { + public SecurityFeatureSet(Settings settings, @Nullable SecurityLicenseState licenseState, + NamedWriteableRegistry namedWriteableRegistry) { this.enabled = Security.enabled(settings); this.licenseState = licenseState; + namedWriteableRegistry.register(Usage.class, Usage.WRITEABLE_NAME, Usage::new); } @Override @@ -43,4 +51,36 @@ public class SecurityFeatureSet implements XPackFeatureSet { public boolean enabled() { return enabled; } + + @Override + public XPackFeatureSet.Usage usage() { + return new Usage(available(), enabled()); + } + + static class Usage extends XPackFeatureSet.Usage { + + private static final String WRITEABLE_NAME = writeableName(Security.NAME); + + public Usage(StreamInput input) throws IOException { + super(input); + } + + public Usage(boolean available, boolean enabled) { + super(Security.NAME, available, enabled); + } + + @Override + public String getWriteableName() { + return WRITEABLE_NAME; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject() + .field(Field.AVAILABLE, available) + .field(Field.ENABLED, enabled) + .endObject(); + + } + } } diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackFeatureSet.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackFeatureSet.java index af26f5ef8d2..ef0717c985d 100644 --- a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackFeatureSet.java +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackFeatureSet.java @@ -5,6 +5,13 @@ */ package org.elasticsearch.xpack; +import org.elasticsearch.common.io.stream.NamedWriteable; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ToXContent; + +import java.io.IOException; + /** * */ @@ -18,4 +25,50 @@ public interface XPackFeatureSet { boolean enabled(); + Usage usage(); + + abstract class Usage implements ToXContent, NamedWriteable { + + protected final String name; + protected final boolean available; + protected final boolean enabled; + + public Usage(StreamInput input) throws IOException { + this(input.readString(), input.readBoolean(), input.readBoolean()); + } + + public Usage(String name, boolean available, boolean enabled) { + this.name = name; + this.available = available; + this.enabled = enabled; + } + + public String name() { + return name; + } + + public boolean available() { + return available; + } + + public boolean enabled() { + return enabled; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeBoolean(available); + out.writeBoolean(enabled); + } + + protected interface Field { + String AVAILABLE = "available"; + String ENABLED = "enabled"; + } + + protected static String writeableName(String featureName) { + return "xpack.usage." + featureName; + } + } + } diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java index 81ad4fc069b..19b705fa770 100644 --- a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java @@ -27,7 +27,9 @@ import org.elasticsearch.script.ScriptModule; import org.elasticsearch.shield.Security; import org.elasticsearch.shield.authc.AuthenticationModule; import org.elasticsearch.xpack.action.TransportXPackInfoAction; +import org.elasticsearch.xpack.action.TransportXPackUsageAction; import org.elasticsearch.xpack.action.XPackInfoAction; +import org.elasticsearch.xpack.action.XPackUsageAction; import org.elasticsearch.xpack.common.http.HttpClientModule; import org.elasticsearch.xpack.common.init.LazyInitializationModule; import org.elasticsearch.xpack.common.init.LazyInitializationService; @@ -37,6 +39,7 @@ import org.elasticsearch.xpack.extensions.XPackExtensionsService; import org.elasticsearch.xpack.notification.Notification; import org.elasticsearch.xpack.rest.action.RestXPackInfoAction; import org.elasticsearch.xpack.common.text.TextTemplateModule; +import org.elasticsearch.xpack.rest.action.RestXPackUsageAction; import org.elasticsearch.xpack.watcher.Watcher; import java.nio.file.Path; @@ -194,6 +197,7 @@ public class XPackPlugin extends Plugin { public void onModule(NetworkModule module) { if (!transportClientMode) { module.registerRestHandler(RestXPackInfoAction.class); + module.registerRestHandler(RestXPackUsageAction.class); } licensing.onModule(module); monitoring.onModule(module); @@ -205,6 +209,7 @@ public class XPackPlugin extends Plugin { public void onModule(ActionModule module) { if (!transportClientMode) { module.registerAction(XPackInfoAction.INSTANCE, TransportXPackInfoAction.class); + module.registerAction(XPackUsageAction.INSTANCE, TransportXPackUsageAction.class); } licensing.onModule(module); monitoring.onModule(module); diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/TransportXPackUsageAction.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/TransportXPackUsageAction.java new file mode 100644 index 00000000000..0aab9211c00 --- /dev/null +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/TransportXPackUsageAction.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.action; + +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.support.ActionFilters; +import org.elasticsearch.action.support.HandledTransportAction; +import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.transport.TransportService; +import org.elasticsearch.xpack.XPackFeatureSet; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + */ +public class TransportXPackUsageAction extends HandledTransportAction { + + private final Set featureSets; + + @Inject + public TransportXPackUsageAction(Settings settings, ThreadPool threadPool, TransportService transportService, + ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver, + Set featureSets) { + super(settings, XPackInfoAction.NAME, threadPool, transportService, actionFilters, indexNameExpressionResolver, + XPackUsageRequest::new); + this.featureSets = featureSets; + } + + @Override + protected void doExecute(XPackUsageRequest request, ActionListener listener) { + List usages = featureSets.stream().map(XPackFeatureSet::usage).collect(Collectors.toList()); + listener.onResponse(new XPackUsageResponse(usages)); + } +} diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackInfoResponse.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackInfoResponse.java index b5bcf9d0228..c7f08ae09c1 100644 --- a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackInfoResponse.java +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackInfoResponse.java @@ -14,7 +14,6 @@ import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.license.core.License; import org.elasticsearch.xpack.XPackBuild; -import org.elasticsearch.xpack.XPackFeatureSet; import java.io.IOException; import java.util.ArrayList; @@ -219,7 +218,7 @@ public class XPackInfoResponse extends ActionResponse { } } - public static class FeatureSet implements XPackFeatureSet, ToXContent, Writeable { + public static class FeatureSet implements ToXContent, Writeable { private final String name; private final @Nullable String description; @@ -237,23 +236,19 @@ public class XPackInfoResponse extends ActionResponse { this.enabled = enabled; } - @Override public String name() { return name; } - @Override @Nullable public String description() { return description; } - @Override public boolean available() { return available; } - @Override public boolean enabled() { return enabled; } diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageAction.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageAction.java new file mode 100644 index 00000000000..6d148f4d5a8 --- /dev/null +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageAction.java @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.action; + +import org.elasticsearch.action.Action; +import org.elasticsearch.client.ElasticsearchClient; + +/** + * + */ +public class XPackUsageAction extends Action { + + public static final String NAME = "cluster:monitor/xpack/usage"; + public static final XPackUsageAction INSTANCE = new XPackUsageAction(); + + public XPackUsageAction() { + super(NAME); + } + + @Override + public XPackUsageRequestBuilder newRequestBuilder(ElasticsearchClient client) { + return new XPackUsageRequestBuilder(client); + } + + @Override + public XPackUsageResponse newResponse() { + return new XPackUsageResponse(); + } +} diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageRequest.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageRequest.java new file mode 100644 index 00000000000..5b91a7565d1 --- /dev/null +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageRequest.java @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.action; + +import org.elasticsearch.action.ActionRequest; +import org.elasticsearch.action.ActionRequestValidationException; + +/** + * + */ +public class XPackUsageRequest extends ActionRequest { + + @Override + public ActionRequestValidationException validate() { + return null; + } + +} diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageRequestBuilder.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageRequestBuilder.java new file mode 100644 index 00000000000..fe1986445ce --- /dev/null +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageRequestBuilder.java @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.action; + +import org.elasticsearch.action.ActionRequestBuilder; +import org.elasticsearch.client.ElasticsearchClient; + +/** + */ +public class XPackUsageRequestBuilder extends ActionRequestBuilder { + + public XPackUsageRequestBuilder(ElasticsearchClient client) { + this(client, XPackUsageAction.INSTANCE); + } + + public XPackUsageRequestBuilder(ElasticsearchClient client, XPackUsageAction action) { + super(client, action, new XPackUsageRequest()); + } +} diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageResponse.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageResponse.java new file mode 100644 index 00000000000..9906acaa181 --- /dev/null +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/action/XPackUsageResponse.java @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.action; + +import org.elasticsearch.action.ActionResponse; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.license.core.License; +import org.elasticsearch.xpack.XPackBuild; +import org.elasticsearch.xpack.XPackFeatureSet; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + */ +public class XPackUsageResponse extends ActionResponse { + + private List usages; + + public XPackUsageResponse() {} + + public XPackUsageResponse(List usages) { + this.usages = usages; + } + + public List getUsages() { + return usages; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + out.writeVInt(usages.size()); + for (XPackFeatureSet.Usage usage : usages) { + out.writeNamedWriteable(usage); + } + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + int size = in.readVInt(); + usages = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + usages.add(in.readNamedWriteable(XPackFeatureSet.Usage.class)); + } + } +} diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/rest/action/RestXPackUsageAction.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/rest/action/RestXPackUsageAction.java new file mode 100644 index 00000000000..1a552fc4a01 --- /dev/null +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/rest/action/RestXPackUsageAction.java @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.rest.action; + +import org.elasticsearch.client.Client; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.rest.BytesRestResponse; +import org.elasticsearch.rest.RestChannel; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.RestResponse; +import org.elasticsearch.rest.action.support.RestBuilderListener; +import org.elasticsearch.xpack.XPackClient; +import org.elasticsearch.xpack.XPackFeatureSet; +import org.elasticsearch.xpack.action.XPackUsageRequestBuilder; +import org.elasticsearch.xpack.action.XPackUsageResponse; +import org.elasticsearch.xpack.rest.XPackRestHandler; + +import static org.elasticsearch.rest.RestRequest.Method.GET; +import static org.elasticsearch.rest.RestStatus.OK; + +public class RestXPackUsageAction extends XPackRestHandler { + + @Inject + public RestXPackUsageAction(Settings settings, RestController controller, Client client) { + super(settings, client); + controller.registerHandler(GET, URI_BASE + "/usage", this); + } + + @Override + protected void handleRequest(RestRequest request, RestChannel restChannel, XPackClient client) throws Exception { + new XPackUsageRequestBuilder(client.es()).execute(new RestBuilderListener(restChannel) { + @Override + public RestResponse buildResponse(XPackUsageResponse response, XContentBuilder builder) throws Exception { + builder.startObject(); + for (XPackFeatureSet.Usage usage : response.getUsages()) { + builder.field(usage.name(), usage); + } + builder.endObject(); + return new BytesRestResponse(OK, builder); + } + }); + } +} diff --git a/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/xpack/watcher/WatcherFeatureSet.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/xpack/watcher/WatcherFeatureSet.java index c39bbec3f94..d57f918469b 100644 --- a/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/xpack/watcher/WatcherFeatureSet.java +++ b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/xpack/watcher/WatcherFeatureSet.java @@ -7,9 +7,14 @@ package org.elasticsearch.xpack.watcher; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.xpack.XPackFeatureSet; +import java.io.IOException; + /** * */ @@ -19,9 +24,10 @@ public class WatcherFeatureSet implements XPackFeatureSet { private final WatcherLicensee licensee; @Inject - public WatcherFeatureSet(Settings settings, @Nullable WatcherLicensee licensee) { + public WatcherFeatureSet(Settings settings, @Nullable WatcherLicensee licensee, NamedWriteableRegistry namedWriteableRegistry) { this.enabled = Watcher.enabled(settings); this.licensee = licensee; + namedWriteableRegistry.register(Usage.class, Usage.WRITEABLE_NAME, Usage::new); } @Override @@ -43,4 +49,36 @@ public class WatcherFeatureSet implements XPackFeatureSet { public boolean enabled() { return enabled; } + + @Override + public Usage usage() { + return new Usage(available(), enabled()); + } + + static class Usage extends XPackFeatureSet.Usage { + + private static final String WRITEABLE_NAME = writeableName(Watcher.NAME); + + public Usage(StreamInput input) throws IOException { + super(input); + } + + public Usage(boolean available, boolean enabled) { + super(Watcher.NAME, available, enabled); + } + + @Override + public String getWriteableName() { + return WRITEABLE_NAME; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject() + .field(Field.AVAILABLE, available) + .field(Field.ENABLED, enabled) + .endObject(); + + } + } }