Skip to content

Commit

Permalink
Enable Universal Profiling as Enterprise feature
Browse files Browse the repository at this point in the history
With this commit we ensure that Universal Profiling can only be used
with an Enterprise license.
  • Loading branch information
danielmitterdorfer committed Oct 5, 2023
1 parent d214d74 commit d930fc5
Show file tree
Hide file tree
Showing 14 changed files with 313 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public final class XPackField {

/** Name constant for the redact processor feature. */
public static final String REDACT_PROCESSOR = "redact_processor";
/* Name for Universal Profiling. */
public static final String UNIVERSAL_PROFILING = "universal_profiling";

private XPackField() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class XPackInfoFeatureAction extends ActionType<XPackInfoFeatureResponse>
public static final XPackInfoFeatureAction AGGREGATE_METRIC = new XPackInfoFeatureAction(XPackField.AGGREGATE_METRIC);
public static final XPackInfoFeatureAction ARCHIVE = new XPackInfoFeatureAction(XPackField.ARCHIVE);
public static final XPackInfoFeatureAction ENTERPRISE_SEARCH = new XPackInfoFeatureAction(XPackField.ENTERPRISE_SEARCH);
public static final XPackInfoFeatureAction UNIVERSAL_PROFILING = new XPackInfoFeatureAction(XPackField.UNIVERSAL_PROFILING);

public static final List<XPackInfoFeatureAction> ALL;
static {
Expand Down Expand Up @@ -80,7 +81,8 @@ public class XPackInfoFeatureAction extends ActionType<XPackInfoFeatureResponse>
DATA_TIERS,
AGGREGATE_METRIC,
ARCHIVE,
ENTERPRISE_SEARCH
ENTERPRISE_SEARCH,
UNIVERSAL_PROFILING
)
);
ALL = Collections.unmodifiableList(actions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class XPackUsageFeatureAction extends ActionType<XPackUsageFeatureRespons
public static final XPackUsageFeatureAction HEALTH = new XPackUsageFeatureAction(XPackField.HEALTH_API);
public static final XPackUsageFeatureAction REMOTE_CLUSTERS = new XPackUsageFeatureAction(XPackField.REMOTE_CLUSTERS);
public static final XPackUsageFeatureAction ENTERPRISE_SEARCH = new XPackUsageFeatureAction(XPackField.ENTERPRISE_SEARCH);
public static final XPackUsageFeatureAction UNIVERSAL_PROFILING = new XPackUsageFeatureAction(XPackField.UNIVERSAL_PROFILING);

static final List<XPackUsageFeatureAction> ALL = List.of(
AGGREGATE_METRIC,
Expand Down Expand Up @@ -78,7 +79,8 @@ public class XPackUsageFeatureAction extends ActionType<XPackUsageFeatureRespons
ARCHIVE,
HEALTH,
REMOTE_CLUSTERS,
ENTERPRISE_SEARCH
ENTERPRISE_SEARCH,
UNIVERSAL_PROFILING
);

// public for testing
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.profiling;

import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;

import java.nio.file.Path;

public class LocalStateProfilingXPackPlugin extends LocalStateCompositeXPackPlugin {
public LocalStateProfilingXPackPlugin(final Settings settings, final Path configPath) {
super(settings, configPath);
plugins.add(new ProfilingPlugin(settings) {
@Override
protected ProfilingLicenseChecker createLicenseChecker() {
return new ProfilingLicenseChecker(LocalStateProfilingXPackPlugin.this::getLicenseState);
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.datastreams.DataStreamsPlugin;
import org.elasticsearch.license.LicenseSettings;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.transport.netty4.Netty4Plugin;
import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.ilm.LifecycleSettings;
import org.elasticsearch.xpack.ilm.IndexLifecycle;
Expand All @@ -37,9 +37,8 @@ public abstract class ProfilingTestCase extends ESIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return List.of(
LocalStateCompositeXPackPlugin.class,
DataStreamsPlugin.class,
ProfilingPlugin.class,
LocalStateProfilingXPackPlugin.class,
IndexLifecycle.class,
UnsignedLongMapperPlugin.class,
VersionFieldPlugin.class,
Expand All @@ -58,6 +57,7 @@ protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) {
// .put(LicenseSettings.SELF_GENERATED_LICENSE_TYPE.getKey(), "trial")
// Disable ILM history index so that the tests don't have to clean it up
.put(LifecycleSettings.LIFECYCLE_HISTORY_INDEX_ENABLED_SETTING.getKey(), false)
.put(LicenseSettings.SELF_GENERATED_LICENSE_TYPE.getKey(), "trial")
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public static class Response extends ActionResponse implements ToXContentObject
private boolean resourcesCreated;
private boolean pre891Data;
private boolean timedOut;
private boolean validLicense;

public Response(StreamInput in) throws IOException {
super(in);
Expand All @@ -44,13 +45,21 @@ public Response(StreamInput in) throws IOException {
resourcesCreated = in.readBoolean();
pre891Data = in.readBoolean();
timedOut = in.readBoolean();
validLicense = in.readBoolean();
}

public Response(boolean profilingEnabled, boolean resourceManagementEnabled, boolean resourcesCreated, boolean pre891Data) {
public Response(
boolean profilingEnabled,
boolean resourceManagementEnabled,
boolean resourcesCreated,
boolean pre891Data,
boolean validLicense
) {
this.profilingEnabled = profilingEnabled;
this.resourceManagementEnabled = resourceManagementEnabled;
this.resourcesCreated = resourcesCreated;
this.pre891Data = pre891Data;
this.validLicense = validLicense;
}

public void setTimedOut(boolean timedOut) {
Expand All @@ -64,7 +73,7 @@ public boolean isResourcesCreated() {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.startObject("profiling").field("enabled", profilingEnabled).endObject();
builder.startObject("profiling").field("enabled", profilingEnabled).field("valid_license", validLicense).endObject();
builder.startObject("resource_management").field("enabled", resourceManagementEnabled).endObject();
builder.startObject("resources").field("created", resourcesCreated).field("pre_8_9_1_data", pre891Data).endObject();
builder.endObject();
Expand All @@ -78,6 +87,7 @@ public void writeTo(StreamOutput out) throws IOException {
out.writeBoolean(resourcesCreated);
out.writeBoolean(pre891Data);
out.writeBoolean(timedOut);
out.writeBoolean(validLicense);
}

@Override
Expand All @@ -89,12 +99,13 @@ public boolean equals(Object o) {
&& resourceManagementEnabled == response.resourceManagementEnabled
&& resourcesCreated == response.resourcesCreated
&& pre891Data == response.pre891Data
&& timedOut == response.timedOut;
&& timedOut == response.timedOut
&& validLicense == response.validLicense;
}

@Override
public int hashCode() {
return Objects.hash(profilingEnabled, resourceManagementEnabled, resourcesCreated, pre891Data, timedOut);
return Objects.hash(profilingEnabled, resourceManagementEnabled, resourcesCreated, pre891Data, timedOut, validLicense);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.profiling;

import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.XPackField;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.action.XPackInfoFeatureAction;
import org.elasticsearch.xpack.core.action.XPackInfoFeatureTransportAction;

public class ProfilingInfoTransportAction extends XPackInfoFeatureTransportAction {
private final boolean enabled;
private final ProfilingLicenseChecker licenseChecker;

@Inject
public ProfilingInfoTransportAction(
TransportService transportService,
ActionFilters actionFilters,
Settings settings,
ProfilingLicenseChecker licenseChecker
) {
super(XPackInfoFeatureAction.UNIVERSAL_PROFILING.name(), transportService, actionFilters);
this.enabled = XPackSettings.PROFILING_ENABLED.get(settings);
this.licenseChecker = licenseChecker;
}

@Override
public String name() {
return XPackField.UNIVERSAL_PROFILING;
}

@Override
public boolean available() {
return licenseChecker.isSupportedLicense();
}

@Override
public boolean enabled() {
return enabled;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.profiling;

import org.elasticsearch.license.License;
import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.LicensedFeature;
import org.elasticsearch.license.XPackLicenseState;

import java.util.function.Supplier;

public final class ProfilingLicenseChecker {
private static final LicensedFeature.Momentary UNIVERSAL_PROFILING_FEATURE = LicensedFeature.momentary(
null,
"universal_profiling",
License.OperationMode.ENTERPRISE
);

private final Supplier<XPackLicenseState> licenseStateResolver;

public ProfilingLicenseChecker(Supplier<XPackLicenseState> licenseStateResolver) {
this.licenseStateResolver = licenseStateResolver;
}

public boolean isSupportedLicense() {
return UNIVERSAL_PROFILING_FEATURE.checkWithoutTracking(licenseStateResolver.get());
}

public void requireSupportedLicense() {
if (UNIVERSAL_PROFILING_FEATURE.check(licenseStateResolver.get()) == false) {
throw LicenseUtils.newComplianceException(UNIVERSAL_PROFILING_FEATURE.getName());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.action.XPackInfoFeatureAction;
import org.elasticsearch.xpack.core.action.XPackUsageFeatureAction;

import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -108,10 +111,12 @@ public Collection<Object> createComponents(
registry.get().initialize();
indexManager.get().initialize();
dataStreamManager.get().initialize();
return List.of(registry.get(), indexManager.get(), dataStreamManager.get());
} else {
return Collections.emptyList();
}
return Collections.singletonList(createLicenseChecker());
}

protected ProfilingLicenseChecker createLicenseChecker() {
return new ProfilingLicenseChecker(XPackPlugin::getSharedLicenseState);
}

public void updateCheckOutdatedIndices(boolean newValue) {
Expand Down Expand Up @@ -179,7 +184,9 @@ public static ExecutorBuilder<?> responseExecutorBuilder() {
return List.of(
new ActionHandler<>(GetStackTracesAction.INSTANCE, TransportGetStackTracesAction.class),
new ActionHandler<>(GetFlamegraphAction.INSTANCE, TransportGetFlamegraphAction.class),
new ActionHandler<>(GetStatusAction.INSTANCE, TransportGetStatusAction.class)
new ActionHandler<>(GetStatusAction.INSTANCE, TransportGetStatusAction.class),
new ActionHandler<>(XPackUsageFeatureAction.UNIVERSAL_PROFILING, ProfilingUsageTransportAction.class),
new ActionHandler<>(XPackInfoFeatureAction.UNIVERSAL_PROFILING, ProfilingInfoTransportAction.class)
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.profiling;

import org.elasticsearch.TransportVersion;
import org.elasticsearch.TransportVersions;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.xpack.core.XPackFeatureSet;
import org.elasticsearch.xpack.core.XPackField;

import java.io.IOException;

public class ProfilingUsage extends XPackFeatureSet.Usage {
public ProfilingUsage(StreamInput input) throws IOException {
super(input);
}

public ProfilingUsage(boolean available, boolean enabled) {
super(XPackField.UNIVERSAL_PROFILING, available, enabled);
}

@Override
public TransportVersion getMinimalSupportedVersion() {
// TODO: This should probably say 8.11.0 but I'm not certain. Check with somebody what's appropriate.
return TransportVersions.V_8_8_1;
}
}
Original file line number Diff line number Diff line change
@@ -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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.profiling;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.protocol.xpack.XPackUsageRequest;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.action.XPackUsageFeatureAction;
import org.elasticsearch.xpack.core.action.XPackUsageFeatureResponse;
import org.elasticsearch.xpack.core.action.XPackUsageFeatureTransportAction;

public class ProfilingUsageTransportAction extends XPackUsageFeatureTransportAction {
private final ProfilingLicenseChecker licenseChecker;

private final boolean enabled;

@Inject
public ProfilingUsageTransportAction(
TransportService transportService,
ClusterService clusterService,
ThreadPool threadPool,
ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver,
ProfilingLicenseChecker licenseChecker,
Settings settings
) {
super(
XPackUsageFeatureAction.UNIVERSAL_PROFILING.name(),
transportService,
clusterService,
threadPool,
actionFilters,
indexNameExpressionResolver
);
this.licenseChecker = licenseChecker;
this.enabled = XPackSettings.PROFILING_ENABLED.get(settings);
}

@Override
protected void masterOperation(
Task task,
XPackUsageRequest request,
ClusterState state,
ActionListener<XPackUsageFeatureResponse> listener
) {
ProfilingUsage profilingUsage = new ProfilingUsage(licenseChecker.isSupportedLicense(), enabled);
listener.onResponse(new XPackUsageFeatureResponse(profilingUsage));
}
}
Loading

0 comments on commit d930fc5

Please sign in to comment.