Adds super basic usage information for searchable snapshots, to be extended later. Backport of #58828
This commit is contained in:
parent
a6109063a2
commit
0b9eb210b8
|
@ -111,6 +111,10 @@ Example response:
|
|||
"available": true,
|
||||
"enabled": true
|
||||
},
|
||||
"searchable_snapshots" : {
|
||||
"available" : true,
|
||||
"enabled" : true
|
||||
},
|
||||
"security" : {
|
||||
"available" : true,
|
||||
"enabled" : false
|
||||
|
|
|
@ -262,6 +262,11 @@ GET /_xpack/usage
|
|||
"available" : true,
|
||||
"enabled" : true
|
||||
},
|
||||
"searchable_snapshots" : {
|
||||
"available" : true,
|
||||
"enabled" : true,
|
||||
"indices_count" : 0
|
||||
},
|
||||
"frozen_indices" : {
|
||||
"available" : true,
|
||||
"enabled" : true,
|
||||
|
|
|
@ -93,7 +93,9 @@ public class XPackLicenseState {
|
|||
|
||||
SPATIAL_GEO_GRID(OperationMode.GOLD, true),
|
||||
|
||||
ANALYTICS(OperationMode.MISSING, true);
|
||||
ANALYTICS(OperationMode.MISSING, true),
|
||||
|
||||
SEARCHABLE_SNAPSHOTS(OperationMode.PLATINUM, true);
|
||||
|
||||
final OperationMode minimumOperationMode;
|
||||
final boolean needsActive;
|
||||
|
|
|
@ -192,6 +192,7 @@ import org.elasticsearch.xpack.core.rollup.job.RollupJobStatus;
|
|||
import org.elasticsearch.xpack.core.async.DeleteAsyncResultAction;
|
||||
import org.elasticsearch.xpack.core.search.action.GetAsyncSearchAction;
|
||||
import org.elasticsearch.xpack.core.search.action.SubmitAsyncSearchAction;
|
||||
import org.elasticsearch.xpack.core.searchablesnapshots.SearchableSnapshotFeatureSetUsage;
|
||||
import org.elasticsearch.xpack.core.security.SecurityFeatureSetUsage;
|
||||
import org.elasticsearch.xpack.core.security.SecurityField;
|
||||
import org.elasticsearch.xpack.core.security.SecuritySettings;
|
||||
|
@ -631,7 +632,10 @@ public class XPackClientPlugin extends Plugin implements ActionPlugin, NetworkPl
|
|||
// analytics
|
||||
new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, XPackField.ANALYTICS, AnalyticsFeatureSetUsage::new),
|
||||
// Enrich
|
||||
new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, XPackField.ENRICH, EnrichFeatureSet.Usage::new)
|
||||
new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, XPackField.ENRICH, EnrichFeatureSet.Usage::new),
|
||||
// Searchable snapshots
|
||||
new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, XPackField.SEARCHABLE_SNAPSHOTS,
|
||||
SearchableSnapshotFeatureSetUsage::new)
|
||||
).stream(),
|
||||
MlEvaluationNamedXContentProvider.getNamedWriteables().stream()
|
||||
).collect(toList());
|
||||
|
|
|
@ -57,6 +57,8 @@ public final class XPackField {
|
|||
public static final String ENRICH = "enrich";
|
||||
/** Name constant for the constant-keyword plugin. */
|
||||
public static final String CONSTANT_KEYWORD = "constant_keyword";
|
||||
/** Name constant for the searchable snapshots feature. */
|
||||
public static final String SEARCHABLE_SNAPSHOTS = "searchable_snapshots";
|
||||
|
||||
private XPackField() {}
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.core.searchablesnapshots;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.xpack.core.XPackFeatureSet;
|
||||
import org.elasticsearch.xpack.core.XPackField;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SearchableSnapshotFeatureSetUsage extends XPackFeatureSet.Usage {
|
||||
|
||||
private final int numberOfSearchableSnapshotIndices;
|
||||
|
||||
public SearchableSnapshotFeatureSetUsage(StreamInput input) throws IOException {
|
||||
super(input);
|
||||
numberOfSearchableSnapshotIndices = input.readVInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getMinimalSupportedVersion() {
|
||||
return Version.V_7_9_0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeVInt(numberOfSearchableSnapshotIndices);
|
||||
}
|
||||
|
||||
public SearchableSnapshotFeatureSetUsage(boolean available,
|
||||
int numberOfSearchableSnapshotIndices) {
|
||||
super(XPackField.SEARCHABLE_SNAPSHOTS, available, true);
|
||||
this.numberOfSearchableSnapshotIndices = numberOfSearchableSnapshotIndices;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void innerXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
super.innerXContent(builder, params);
|
||||
builder.field("indices_count", numberOfSearchableSnapshotIndices);
|
||||
}
|
||||
|
||||
public int getNumberOfSearchableSnapshotIndices() {
|
||||
return numberOfSearchableSnapshotIndices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(available, enabled, numberOfSearchableSnapshotIndices);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
SearchableSnapshotFeatureSetUsage other = (SearchableSnapshotFeatureSetUsage) obj;
|
||||
return Objects.equals(available, other.available) &&
|
||||
Objects.equals(enabled, other.enabled) &&
|
||||
Objects.equals(numberOfSearchableSnapshotIndices, other.numberOfSearchableSnapshotIndices);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.core.searchablesnapshots;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.xpack.core.XPackFeatureSet;
|
||||
import org.elasticsearch.xpack.core.XPackField;
|
||||
import org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SearchableSnapshotsFeatureSet implements XPackFeatureSet {
|
||||
|
||||
private final XPackLicenseState licenseState;
|
||||
private final ClusterService clusterService;
|
||||
|
||||
@Inject
|
||||
public SearchableSnapshotsFeatureSet(@Nullable XPackLicenseState licenseState, ClusterService clusterService) {
|
||||
this.licenseState = licenseState;
|
||||
this.clusterService = clusterService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return XPackField.SEARCHABLE_SNAPSHOTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean available() {
|
||||
return licenseState.isAllowed(XPackLicenseState.Feature.SEARCHABLE_SNAPSHOTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> nativeCodeInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void usage(ActionListener<XPackFeatureSet.Usage> listener) {
|
||||
ClusterState state = clusterService.state();
|
||||
int numSnapIndices = 0;
|
||||
for (IndexMetadata indexMetadata : state.metadata()) {
|
||||
if (SearchableSnapshotsConstants.isSearchableSnapshotStore(indexMetadata.getSettings())) {
|
||||
numSnapIndices++;
|
||||
}
|
||||
}
|
||||
listener.onResponse(
|
||||
new SearchableSnapshotFeatureSetUsage(
|
||||
available(),
|
||||
numSnapIndices
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.core.searchablesnapshots;
|
||||
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SearchableSnapshotsFeatureSetUsageTests extends AbstractWireSerializingTestCase<SearchableSnapshotFeatureSetUsage> {
|
||||
|
||||
@Override
|
||||
protected SearchableSnapshotFeatureSetUsage createTestInstance() {
|
||||
boolean available = randomBoolean();
|
||||
return new SearchableSnapshotFeatureSetUsage(available, randomIntBetween(0, 100000));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SearchableSnapshotFeatureSetUsage mutateInstance(SearchableSnapshotFeatureSetUsage instance) throws IOException {
|
||||
boolean available = instance.available();
|
||||
int numSearchableSnapshotIndices = instance.getNumberOfSearchableSnapshotIndices();
|
||||
switch (between(0, 1)) {
|
||||
case 0:
|
||||
available = available == false;
|
||||
break;
|
||||
case 1:
|
||||
numSearchableSnapshotIndices = randomValueOtherThan(numSearchableSnapshotIndices, () -> randomIntBetween(0, 100000));
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
return new SearchableSnapshotFeatureSetUsage(available, numSearchableSnapshotIndices);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Writeable.Reader<SearchableSnapshotFeatureSetUsage> instanceReader() {
|
||||
return SearchableSnapshotFeatureSetUsage::new;
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@ import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
|||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||
import org.elasticsearch.cluster.routing.allocation.ExistingShardsAllocator;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.IndexScopedSettings;
|
||||
|
@ -31,7 +32,6 @@ import org.elasticsearch.index.engine.EngineFactory;
|
|||
import org.elasticsearch.index.engine.ReadOnlyEngine;
|
||||
import org.elasticsearch.index.store.SearchableSnapshotDirectory;
|
||||
import org.elasticsearch.index.translog.TranslogStats;
|
||||
import org.elasticsearch.license.License;
|
||||
import org.elasticsearch.license.LicenseUtils;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
|
@ -47,7 +47,9 @@ import org.elasticsearch.threadpool.ExecutorBuilder;
|
|||
import org.elasticsearch.threadpool.ScalingExecutorBuilder;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.core.XPackPlugin;
|
||||
import org.elasticsearch.xpack.core.searchablesnapshots.MountSearchableSnapshotAction;
|
||||
import org.elasticsearch.xpack.core.searchablesnapshots.SearchableSnapshotsFeatureSet;
|
||||
import org.elasticsearch.xpack.searchablesnapshots.action.ClearSearchableSnapshotsCacheAction;
|
||||
import org.elasticsearch.xpack.searchablesnapshots.action.RepositoryStatsAction;
|
||||
import org.elasticsearch.xpack.searchablesnapshots.action.SearchableSnapshotsStatsAction;
|
||||
|
@ -137,12 +139,15 @@ public class SearchableSnapshots extends Plugin implements IndexStorePlugin, Eng
|
|||
private final SetOnce<ThreadPool> threadPool = new SetOnce<>();
|
||||
private final Settings settings;
|
||||
|
||||
private final boolean transportClientMode;
|
||||
|
||||
public SearchableSnapshots(final Settings settings) {
|
||||
this.settings = settings;
|
||||
this.transportClientMode = XPackPlugin.transportClientMode(settings);
|
||||
}
|
||||
|
||||
public static void ensureValidLicense(XPackLicenseState licenseState) {
|
||||
if (licenseState.isAllowedByLicense(License.OperationMode.PLATINUM) == false) {
|
||||
if (licenseState.isAllowed(XPackLicenseState.Feature.SEARCHABLE_SNAPSHOTS) == false) {
|
||||
throw LicenseUtils.newComplianceException("searchable-snapshots");
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +201,19 @@ public class SearchableSnapshots extends Plugin implements IndexStorePlugin, Eng
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Module> createGuiceModules() {
|
||||
if (SEARCHABLE_SNAPSHOTS_FEATURE_ENABLED) {
|
||||
if (transportClientMode) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Collections.singleton(b -> XPackPlugin.bindFeatureSet(b, SearchableSnapshotsFeatureSet.class));
|
||||
} else {
|
||||
return org.elasticsearch.common.collect.List.of();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIndexModule(IndexModule indexModule) {
|
||||
if (SearchableSnapshotsConstants.isSearchableSnapshotStore(indexModule.getSettings())) {
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
setup:
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: docs
|
||||
body:
|
||||
settings:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
body:
|
||||
- index:
|
||||
_index: docs
|
||||
_id: 1
|
||||
- field: foo
|
||||
- index:
|
||||
_index: docs
|
||||
_id: 2
|
||||
- field: bar
|
||||
- index:
|
||||
_index: docs
|
||||
_id: 3
|
||||
- field: baz
|
||||
|
||||
- do:
|
||||
snapshot.create_repository:
|
||||
repository: repository-fs
|
||||
body:
|
||||
type: fs
|
||||
settings:
|
||||
location: "repository-fs"
|
||||
|
||||
# Remove the snapshot if a previous test failed to delete it.
|
||||
# Useful for third party tests that runs the test against a real external service.
|
||||
- do:
|
||||
snapshot.delete:
|
||||
repository: repository-fs
|
||||
snapshot: snapshot
|
||||
ignore: 404
|
||||
|
||||
- do:
|
||||
snapshot.create:
|
||||
repository: repository-fs
|
||||
snapshot: snapshot
|
||||
wait_for_completion: true
|
||||
|
||||
- do:
|
||||
indices.delete:
|
||||
index: docs
|
||||
---
|
||||
teardown:
|
||||
|
||||
- do:
|
||||
snapshot.delete:
|
||||
repository: repository-fs
|
||||
snapshot: snapshot
|
||||
ignore: 404
|
||||
|
||||
- do:
|
||||
snapshot.delete_repository:
|
||||
repository: repository-fs
|
||||
|
||||
---
|
||||
"Tests searchable snapshots usage stats":
|
||||
- skip:
|
||||
version: " - 7.8.99"
|
||||
reason: searchable snapshots usage stats introduced in 7.9.0
|
||||
|
||||
- do:
|
||||
xpack.usage: {}
|
||||
|
||||
- match: { searchable_snapshots.available: true }
|
||||
- match: { searchable_snapshots.enabled: true }
|
||||
- match: { searchable_snapshots.indices_count: 0 }
|
||||
|
||||
- do:
|
||||
searchable_snapshots.mount:
|
||||
repository: repository-fs
|
||||
snapshot: snapshot
|
||||
wait_for_completion: true
|
||||
body:
|
||||
index: docs
|
||||
|
||||
- match: { snapshot.snapshot: snapshot }
|
||||
- match: { snapshot.shards.failed: 0 }
|
||||
- match: { snapshot.shards.successful: 1 }
|
||||
|
||||
- do:
|
||||
xpack.usage: {}
|
||||
|
||||
- match: { searchable_snapshots.available: true }
|
||||
- match: { searchable_snapshots.enabled: true }
|
||||
- match: { searchable_snapshots.indices_count: 1 }
|
Loading…
Reference in New Issue