Make IndexTemplateRegistry project-aware (#126986)

Ensures the `IndexTemplatesRegistry` installs resources in every project
in the cluster.

ES-10055
This commit is contained in:
Niels Bauman 2025-04-24 12:22:18 +02:00 committed by GitHub
parent 7b95ec4767
commit ff1c9b7c6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
55 changed files with 549 additions and 289 deletions

View file

@ -21,6 +21,7 @@ import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.metadata.ProjectId; import org.elasticsearch.cluster.metadata.ProjectId;
import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.metadata.ProjectMetadata;
import org.elasticsearch.core.CheckedRunnable; import org.elasticsearch.core.CheckedRunnable;
import org.elasticsearch.core.FixForMultiProject;
import java.util.Collection; import java.util.Collection;
import java.util.Objects; import java.util.Objects;
@ -94,6 +95,7 @@ public interface ProjectResolver extends ProjectIdResolver {
/** /**
* Returns a client that executes every request in the context of the given project. * Returns a client that executes every request in the context of the given project.
*/ */
@FixForMultiProject(description = "This recreates a client on every invocation. We should optimize this to be less wasteful")
default Client projectClient(Client baseClient, ProjectId projectId) { default Client projectClient(Client baseClient, ProjectId projectId) {
// We only take the shortcut when the given project ID matches the "current" project ID. If it doesn't, we'll let #executeOnProject // We only take the shortcut when the given project ID matches the "current" project ID. If it doesn't, we'll let #executeOnProject
// take care of error handling. // take care of error handling.

View file

@ -62,7 +62,7 @@ public final class TestProjectResolvers {
public static ProjectResolver mustExecuteFirst() { public static ProjectResolver mustExecuteFirst() {
return new ProjectResolver() { return new ProjectResolver() {
private ProjectId enforceProjectId = null; private volatile ProjectId enforceProjectId = null;
@Override @Override
public ProjectId getProjectId() { public ProjectId getProjectId() {
@ -81,14 +81,16 @@ public final class TestProjectResolvers {
@Override @Override
public <E extends Exception> void executeOnProject(ProjectId projectId, CheckedRunnable<E> body) throws E { public <E extends Exception> void executeOnProject(ProjectId projectId, CheckedRunnable<E> body) throws E {
if (enforceProjectId != null) { synchronized (this) {
throw new IllegalStateException("Cannot nest calls to executeOnProject"); if (enforceProjectId != null) {
} throw new IllegalStateException("Cannot nest calls to executeOnProject");
try { }
enforceProjectId = projectId; try {
body.run(); enforceProjectId = projectId;
} finally { body.run();
enforceProjectId = null; } finally {
enforceProjectId = null;
}
} }
} }

View file

@ -2817,16 +2817,12 @@ public abstract class ESRestTestCase extends ESTestCase {
if (indexTemplates != null) { if (indexTemplates != null) {
var templateNames = indexTemplates.keySet().stream().filter(name -> isXPackTemplate(name) == false).toList(); var templateNames = indexTemplates.keySet().stream().filter(name -> isXPackTemplate(name) == false).toList();
assertThat("Project [" + projectId + "] should not have index templates", templateNames, empty()); assertThat("Project [" + projectId + "] should not have index templates", templateNames, empty());
} else if (projectId.equals(Metadata.DEFAULT_PROJECT_ID.id())) {
fail("Expected default project to have standard templates, but was null");
} }
final Map<String, Object> componentTemplates = state.evaluate("metadata.component_template.component_template"); final Map<String, Object> componentTemplates = state.evaluate("metadata.component_template.component_template");
if (componentTemplates != null) { if (componentTemplates != null) {
var templateNames = componentTemplates.keySet().stream().filter(name -> isXPackTemplate(name) == false).toList(); var templateNames = componentTemplates.keySet().stream().filter(name -> isXPackTemplate(name) == false).toList();
assertThat("Project [" + projectId + "] should not have component templates", templateNames, empty()); assertThat("Project [" + projectId + "] should not have component templates", templateNames, empty());
} else if (projectId.equals(Metadata.DEFAULT_PROJECT_ID.id())) {
fail("Expected default project to have standard component templates, but was null");
} }
final List<Map<String, ?>> pipelines = state.evaluate("metadata.ingest.pipeline"); final List<Map<String, ?>> pipelines = state.evaluate("metadata.ingest.pipeline");
@ -2836,8 +2832,6 @@ public abstract class ESRestTestCase extends ESTestCase {
.filter(id -> isXPackIngestPipeline(id) == false) .filter(id -> isXPackIngestPipeline(id) == false)
.toList(); .toList();
assertThat("Project [" + projectId + "] should not have ingest pipelines", pipelineNames, empty()); assertThat("Project [" + projectId + "] should not have ingest pipelines", pipelineNames, empty());
} else if (projectId.equals(Metadata.DEFAULT_PROJECT_ID.id())) {
fail("Expected default project to have standard ingest pipelines, but was null");
} }
if (has(ProductFeature.ILM)) { if (has(ProductFeature.ILM)) {
@ -2846,8 +2840,6 @@ public abstract class ESRestTestCase extends ESTestCase {
var policyNames = new HashSet<>(ilmPolicies.keySet()); var policyNames = new HashSet<>(ilmPolicies.keySet());
policyNames.removeAll(preserveILMPolicyIds()); policyNames.removeAll(preserveILMPolicyIds());
assertThat("Project [" + projectId + "] should not have ILM Policies", policyNames, empty()); assertThat("Project [" + projectId + "] should not have ILM Policies", policyNames, empty());
} else if (projectId.equals(Metadata.DEFAULT_PROJECT_ID.id())) {
fail("Expected default project to have standard ILM policies, but was null");
} }
} }
} }

View file

@ -8,6 +8,7 @@
package org.elasticsearch.xpack.apmdata; package org.elasticsearch.xpack.apmdata;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -32,7 +33,8 @@ public class APMIndexTemplateRegistry extends YamlTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super( super(
nodeSettings, nodeSettings,
@ -40,7 +42,8 @@ public class APMIndexTemplateRegistry extends YamlTemplateRegistry {
threadPool, threadPool,
client, client,
xContentRegistry, xContentRegistry,
templateFilter(isDataStreamsLifecycleOnlyMode(clusterService.getSettings())) templateFilter(isDataStreamsLifecycleOnlyMode(clusterService.getSettings())),
projectResolver
); );
} }

View file

@ -48,7 +48,14 @@ public class APMPlugin extends Plugin implements ActionPlugin {
Settings settings = services.environment().settings(); Settings settings = services.environment().settings();
ClusterService clusterService = services.clusterService(); ClusterService clusterService = services.clusterService();
registry.set( registry.set(
new APMIndexTemplateRegistry(settings, clusterService, services.threadPool(), services.client(), services.xContentRegistry()) new APMIndexTemplateRegistry(
settings,
clusterService,
services.threadPool(),
services.client(),
services.xContentRegistry(),
services.projectResolver()
)
); );
if (enabled) { if (enabled) {
APMIndexTemplateRegistry registryInstance = registry.get(); APMIndexTemplateRegistry registryInstance = registry.get();

View file

@ -11,6 +11,7 @@ import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.DataStreamLifecycle; import org.elasticsearch.cluster.metadata.DataStreamLifecycle;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -59,7 +60,8 @@ public class APMDSLOnlyTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
NamedXContentRegistry.EMPTY NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
); );
apmIndexTemplateRegistry.setEnabled(true); apmIndexTemplateRegistry.setEnabled(true);
} }

View file

@ -26,6 +26,8 @@ import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -89,8 +91,9 @@ public class APMIndexTemplateRegistryTests extends ESTestCase {
threadPool = new TestThreadPool(this.getClass().getName()); threadPool = new TestThreadPool(this.getClass().getName());
client = new VerifyingClient(threadPool); client = new VerifyingClient(threadPool);
ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool, clusterSettings); ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool, clusterSettings);
ProjectResolver projectResolver = TestProjectResolvers.mustExecuteFirst();
stackTemplateRegistryAccessor = new StackTemplateRegistryAccessor( stackTemplateRegistryAccessor = new StackTemplateRegistryAccessor(
new StackTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, NamedXContentRegistry.EMPTY) new StackTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, NamedXContentRegistry.EMPTY, projectResolver)
); );
apmIndexTemplateRegistry = new APMIndexTemplateRegistry( apmIndexTemplateRegistry = new APMIndexTemplateRegistry(
@ -98,7 +101,8 @@ public class APMIndexTemplateRegistryTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
NamedXContentRegistry.EMPTY NamedXContentRegistry.EMPTY,
projectResolver
); );
apmIndexTemplateRegistry.setEnabled(true); apmIndexTemplateRegistry.setEnabled(true);
} }

View file

@ -17,6 +17,7 @@ import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterChangedEvent;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.DataStream; import org.elasticsearch.cluster.metadata.DataStream;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.datastreams.DataStreamsPlugin; import org.elasticsearch.datastreams.DataStreamsPlugin;
import org.elasticsearch.index.mapper.DateFieldMapper; import org.elasticsearch.index.mapper.DateFieldMapper;
@ -58,7 +59,8 @@ public class IndexTemplateRegistryRolloverIT extends ESIntegTestCase {
clusterService.threadPool(), clusterService.threadPool(),
client, client,
xContentRegistry(), xContentRegistry(),
3L 3L,
TestProjectResolvers.mustExecuteFirst()
); );
registry.initialize(); registry.initialize();
ensureGreen(); ensureGreen();

View file

@ -9,6 +9,7 @@ package org.elasticsearch.xpack.core.template;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -28,9 +29,10 @@ public class RolloverEnabledTestTemplateRegistry extends IndexTemplateRegistry {
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry, NamedXContentRegistry xContentRegistry,
long version long version,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
this.version = version; this.version = version;
} }

View file

@ -30,9 +30,11 @@ import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.metadata.DataStream; import org.elasticsearch.cluster.metadata.DataStream;
import org.elasticsearch.cluster.metadata.IndexTemplateMetadata; import org.elasticsearch.cluster.metadata.IndexTemplateMetadata;
import org.elasticsearch.cluster.metadata.MetadataIndexTemplateService; import org.elasticsearch.cluster.metadata.MetadataIndexTemplateService;
import org.elasticsearch.cluster.metadata.ProjectId;
import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.metadata.ProjectMetadata;
import org.elasticsearch.cluster.metadata.Template; import org.elasticsearch.cluster.metadata.Template;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.regex.Regex;
@ -85,10 +87,14 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
protected final ThreadPool threadPool; protected final ThreadPool threadPool;
protected final NamedXContentRegistry xContentRegistry; protected final NamedXContentRegistry xContentRegistry;
protected final ClusterService clusterService; protected final ClusterService clusterService;
protected final ConcurrentMap<String, AtomicBoolean> templateCreationsInProgress = new ConcurrentHashMap<>(); protected final ConcurrentMap<ProjectId, ConcurrentHashMap<String, AtomicBoolean>> templateCreationsInProgress =
protected final ConcurrentMap<String, AtomicBoolean> policyCreationsInProgress = new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
protected final ConcurrentMap<String, AtomicBoolean> pipelineCreationsInProgress = new ConcurrentHashMap<>(); protected final ConcurrentMap<ProjectId, ConcurrentHashMap<String, AtomicBoolean>> policyCreationsInProgress =
new ConcurrentHashMap<>();
protected final ConcurrentMap<ProjectId, ConcurrentHashMap<String, AtomicBoolean>> pipelineCreationsInProgress =
new ConcurrentHashMap<>();
protected final List<LifecyclePolicy> lifecyclePolicies; protected final List<LifecyclePolicy> lifecyclePolicies;
protected final ProjectResolver projectResolver;
@SuppressWarnings("this-escape") @SuppressWarnings("this-escape")
public IndexTemplateRegistry( public IndexTemplateRegistry(
@ -96,13 +102,15 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
this.settings = nodeSettings; this.settings = nodeSettings;
this.client = client; this.client = client;
this.threadPool = threadPool; this.threadPool = threadPool;
this.xContentRegistry = xContentRegistry; this.xContentRegistry = xContentRegistry;
this.clusterService = clusterService; this.clusterService = clusterService;
this.projectResolver = projectResolver;
if (isDataStreamsLifecycleOnlyMode(clusterService.getSettings()) == false) { if (isDataStreamsLifecycleOnlyMode(clusterService.getSettings()) == false) {
this.lifecyclePolicies = getLifecycleConfigs().stream() this.lifecyclePolicies = getLifecycleConfigs().stream()
.map(config -> config.load(LifecyclePolicyConfig.DEFAULT_X_CONTENT_REGISTRY)) .map(config -> config.load(LifecyclePolicyConfig.DEFAULT_X_CONTENT_REGISTRY))
@ -235,10 +243,13 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
DiscoveryNode localNode = event.state().getNodes().getLocalNode(); DiscoveryNode localNode = event.state().getNodes().getLocalNode();
boolean localNodeVersionAfterMaster = localNode.getVersion().after(masterNode.getVersion()); boolean localNodeVersionAfterMaster = localNode.getVersion().after(masterNode.getVersion());
if (event.localNodeMaster() || localNodeVersionAfterMaster) { if (event.localNodeMaster() == false && localNodeVersionAfterMaster == false) {
addIngestPipelinesIfMissing(state); return;
addTemplatesIfMissing(state); }
addIndexLifecyclePoliciesIfMissing(state); for (ProjectMetadata project : event.state().metadata().projects().values()) {
addIngestPipelinesIfMissing(project);
addTemplatesIfMissing(project);
addIndexLifecyclePoliciesIfMissing(project);
} }
} }
@ -259,13 +270,13 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
return false; return false;
} }
private void addTemplatesIfMissing(ClusterState state) { private void addTemplatesIfMissing(ProjectMetadata project) {
addLegacyTemplatesIfMissing(state); addLegacyTemplatesIfMissing(project);
addComponentTemplatesIfMissing(state); addComponentTemplatesIfMissing(project);
addComposableTemplatesIfMissing(state.metadata().getProject()); addComposableTemplatesIfMissing(project);
} }
private void addLegacyTemplatesIfMissing(ClusterState state) { private void addLegacyTemplatesIfMissing(ProjectMetadata project) {
if (isDataStreamsLifecycleOnlyMode(clusterService.getSettings())) { if (isDataStreamsLifecycleOnlyMode(clusterService.getSettings())) {
// data stream lifecycle cannot be configured via legacy templates // data stream lifecycle cannot be configured via legacy templates
return; return;
@ -273,12 +284,13 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
final List<IndexTemplateConfig> indexTemplates = getLegacyTemplateConfigs(); final List<IndexTemplateConfig> indexTemplates = getLegacyTemplateConfigs();
for (IndexTemplateConfig newTemplate : indexTemplates) { for (IndexTemplateConfig newTemplate : indexTemplates) {
final String templateName = newTemplate.getTemplateName(); final String templateName = newTemplate.getTemplateName();
final AtomicBoolean creationCheck = templateCreationsInProgress.computeIfAbsent(templateName, key -> new AtomicBoolean(false)); final AtomicBoolean creationCheck = templateCreationsInProgress.computeIfAbsent(project.id(), key -> new ConcurrentHashMap<>())
.computeIfAbsent(templateName, key -> new AtomicBoolean(false));
if (creationCheck.compareAndSet(false, true)) { if (creationCheck.compareAndSet(false, true)) {
IndexTemplateMetadata currentTemplate = state.metadata().getProject().templates().get(templateName); IndexTemplateMetadata currentTemplate = project.templates().get(templateName);
if (Objects.isNull(currentTemplate)) { if (Objects.isNull(currentTemplate)) {
logger.debug("adding legacy template [{}] for [{}], because it doesn't exist", templateName, getOrigin()); logger.debug("adding legacy template [{}] for [{}], because it doesn't exist", templateName, getOrigin());
putLegacyTemplate(newTemplate, creationCheck); putLegacyTemplate(project.id(), newTemplate, creationCheck);
} else if (Objects.isNull(currentTemplate.getVersion()) || newTemplate.getVersion() > currentTemplate.getVersion()) { } else if (Objects.isNull(currentTemplate.getVersion()) || newTemplate.getVersion() > currentTemplate.getVersion()) {
// IndexTemplateConfig now enforces templates contain a `version` property, so if the template doesn't have one we can // IndexTemplateConfig now enforces templates contain a `version` property, so if the template doesn't have one we can
// safely assume it's an old version of the template. // safely assume it's an old version of the template.
@ -289,7 +301,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
currentTemplate.getVersion(), currentTemplate.getVersion(),
newTemplate.getVersion() newTemplate.getVersion()
); );
putLegacyTemplate(newTemplate, creationCheck); putLegacyTemplate(project.id(), newTemplate, creationCheck);
} else { } else {
creationCheck.set(false); creationCheck.set(false);
logger.trace( logger.trace(
@ -309,14 +321,15 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
} }
} }
private void addComponentTemplatesIfMissing(ClusterState state) { private void addComponentTemplatesIfMissing(ProjectMetadata project) {
final Map<String, ComponentTemplate> indexTemplates = getComponentTemplateConfigs(); final Map<String, ComponentTemplate> indexTemplates = getComponentTemplateConfigs();
for (Map.Entry<String, ComponentTemplate> newTemplate : indexTemplates.entrySet()) { for (Map.Entry<String, ComponentTemplate> newTemplate : indexTemplates.entrySet()) {
final String templateName = newTemplate.getKey(); final String templateName = newTemplate.getKey();
final AtomicBoolean creationCheck = templateCreationsInProgress.computeIfAbsent(templateName, key -> new AtomicBoolean(false)); final AtomicBoolean creationCheck = templateCreationsInProgress.computeIfAbsent(project.id(), key -> new ConcurrentHashMap<>())
.computeIfAbsent(templateName, key -> new AtomicBoolean(false));
if (creationCheck.compareAndSet(false, true)) { if (creationCheck.compareAndSet(false, true)) {
ComponentTemplate currentTemplate = state.metadata().getProject().componentTemplates().get(templateName); ComponentTemplate currentTemplate = project.componentTemplates().get(templateName);
if (templateDependenciesSatisfied(state, newTemplate.getValue()) == false) { if (templateDependenciesSatisfied(project, newTemplate.getValue()) == false) {
creationCheck.set(false); creationCheck.set(false);
logger.trace( logger.trace(
"not adding index template [{}] for [{}] because its required dependencies do not exist", "not adding index template [{}] for [{}] because its required dependencies do not exist",
@ -325,7 +338,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
); );
} else if (Objects.isNull(currentTemplate)) { } else if (Objects.isNull(currentTemplate)) {
logger.debug("adding component template [{}] for [{}], because it doesn't exist", templateName, getOrigin()); logger.debug("adding component template [{}] for [{}], because it doesn't exist", templateName, getOrigin());
putComponentTemplate(templateName, newTemplate.getValue(), creationCheck); putComponentTemplate(project.id(), templateName, newTemplate.getValue(), creationCheck);
} else if (Objects.isNull(currentTemplate.version()) || newTemplate.getValue().version() > currentTemplate.version()) { } else if (Objects.isNull(currentTemplate.version()) || newTemplate.getValue().version() > currentTemplate.version()) {
// IndexTemplateConfig now enforces templates contain a `version` property, so if the template doesn't have one we can // IndexTemplateConfig now enforces templates contain a `version` property, so if the template doesn't have one we can
// safely assume it's an old version of the template. // safely assume it's an old version of the template.
@ -336,7 +349,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
currentTemplate.version(), currentTemplate.version(),
newTemplate.getValue().version() newTemplate.getValue().version()
); );
putComponentTemplate(templateName, newTemplate.getValue(), creationCheck); putComponentTemplate(project.id(), templateName, newTemplate.getValue(), creationCheck);
} else { } else {
creationCheck.set(false); creationCheck.set(false);
logger.trace( logger.trace(
@ -359,7 +372,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
/** /**
* Returns true if the cluster state contains all of the dependencies required by the provided component template * Returns true if the cluster state contains all of the dependencies required by the provided component template
*/ */
private static boolean templateDependenciesSatisfied(ClusterState state, ComponentTemplate indexTemplate) { private static boolean templateDependenciesSatisfied(ProjectMetadata project, ComponentTemplate indexTemplate) {
Template template = indexTemplate.template(); Template template = indexTemplate.template();
if (template == null) { if (template == null) {
return true; return true;
@ -368,7 +381,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
if (settings == null) { if (settings == null) {
return true; return true;
} }
IngestMetadata ingestMetadata = state.metadata().getProject().custom(IngestMetadata.TYPE); IngestMetadata ingestMetadata = project.custom(IngestMetadata.TYPE);
String defaultPipeline = settings.get("index.default_pipeline"); String defaultPipeline = settings.get("index.default_pipeline");
if (defaultPipeline != null) { if (defaultPipeline != null) {
if (ingestMetadata == null || ingestMetadata.getPipelines().containsKey(defaultPipeline) == false) { if (ingestMetadata == null || ingestMetadata.getPipelines().containsKey(defaultPipeline) == false) {
@ -382,14 +395,15 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
return true; return true;
} }
private void addComposableTemplatesIfMissing(ProjectMetadata projectMetadata) { private void addComposableTemplatesIfMissing(ProjectMetadata project) {
final Map<String, ComposableIndexTemplate> indexTemplates = getComposableTemplateConfigs(); final Map<String, ComposableIndexTemplate> indexTemplates = getComposableTemplateConfigs();
for (Map.Entry<String, ComposableIndexTemplate> newTemplate : indexTemplates.entrySet()) { for (Map.Entry<String, ComposableIndexTemplate> newTemplate : indexTemplates.entrySet()) {
final String templateName = newTemplate.getKey(); final String templateName = newTemplate.getKey();
final AtomicBoolean creationCheck = templateCreationsInProgress.computeIfAbsent(templateName, key -> new AtomicBoolean(false)); final AtomicBoolean creationCheck = templateCreationsInProgress.computeIfAbsent(project.id(), key -> new ConcurrentHashMap<>())
.computeIfAbsent(templateName, key -> new AtomicBoolean(false));
if (creationCheck.compareAndSet(false, true)) { if (creationCheck.compareAndSet(false, true)) {
ComposableIndexTemplate currentTemplate = projectMetadata.templatesV2().get(templateName); ComposableIndexTemplate currentTemplate = project.templatesV2().get(templateName);
boolean componentTemplatesAvailable = componentTemplatesInstalled(projectMetadata, newTemplate.getValue()); boolean componentTemplatesAvailable = componentTemplatesInstalled(project, newTemplate.getValue());
if (componentTemplatesAvailable == false) { if (componentTemplatesAvailable == false) {
creationCheck.set(false); creationCheck.set(false);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
@ -402,7 +416,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
} }
} else if (Objects.isNull(currentTemplate)) { } else if (Objects.isNull(currentTemplate)) {
logger.debug("adding composable template [{}] for [{}], because it doesn't exist", templateName, getOrigin()); logger.debug("adding composable template [{}] for [{}], because it doesn't exist", templateName, getOrigin());
putComposableTemplate(projectMetadata, templateName, newTemplate.getValue(), creationCheck); putComposableTemplate(project, templateName, newTemplate.getValue(), creationCheck);
} else if (Objects.isNull(currentTemplate.version()) || newTemplate.getValue().version() > currentTemplate.version()) { } else if (Objects.isNull(currentTemplate.version()) || newTemplate.getValue().version() > currentTemplate.version()) {
// IndexTemplateConfig now enforces templates contain a `version` property, so if the template doesn't have one we can // IndexTemplateConfig now enforces templates contain a `version` property, so if the template doesn't have one we can
// safely assume it's an old version of the template. // safely assume it's an old version of the template.
@ -413,7 +427,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
currentTemplate.version(), currentTemplate.version(),
newTemplate.getValue().version() newTemplate.getValue().version()
); );
putComposableTemplate(projectMetadata, templateName, newTemplate.getValue(), creationCheck); putComposableTemplate(project, templateName, newTemplate.getValue(), creationCheck);
} else { } else {
creationCheck.set(false); creationCheck.set(false);
logger.trace( logger.trace(
@ -438,14 +452,14 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
* requires automatic rollover after index template upgrades (see {@link #applyRolloverAfterTemplateV2Update()}), this method also * requires automatic rollover after index template upgrades (see {@link #applyRolloverAfterTemplateV2Update()}), this method also
* verifies that the installed components templates are of the right version. * verifies that the installed components templates are of the right version.
*/ */
private boolean componentTemplatesInstalled(ProjectMetadata projectMetadata, ComposableIndexTemplate indexTemplate) { private boolean componentTemplatesInstalled(ProjectMetadata project, ComposableIndexTemplate indexTemplate) {
if (applyRolloverAfterTemplateV2Update() == false) { if (applyRolloverAfterTemplateV2Update() == false) {
// component templates and index templates can be updated independently, we only need to know that the required component // component templates and index templates can be updated independently, we only need to know that the required component
// templates are available // templates are available
return projectMetadata.componentTemplates().keySet().containsAll(indexTemplate.getRequiredComponentTemplates()); return project.componentTemplates().keySet().containsAll(indexTemplate.getRequiredComponentTemplates());
} }
Map<String, ComponentTemplate> componentTemplateConfigs = getComponentTemplateConfigs(); Map<String, ComponentTemplate> componentTemplateConfigs = getComponentTemplateConfigs();
Map<String, ComponentTemplate> installedTemplates = projectMetadata.componentTemplates(); Map<String, ComponentTemplate> installedTemplates = project.componentTemplates();
for (String templateName : indexTemplate.getRequiredComponentTemplates()) { for (String templateName : indexTemplate.getRequiredComponentTemplates()) {
ComponentTemplate installedTemplate = installedTemplates.get(templateName); ComponentTemplate installedTemplate = installedTemplates.get(templateName);
// if a required component templates is not installed - the current cluster state cannot allow this index template yet // if a required component templates is not installed - the current cluster state cannot allow this index template yet
@ -463,7 +477,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
return true; return true;
} }
private void putLegacyTemplate(final IndexTemplateConfig config, final AtomicBoolean creationCheck) { private void putLegacyTemplate(final ProjectId projectId, final IndexTemplateConfig config, final AtomicBoolean creationCheck) {
final Executor executor = threadPool.generic(); final Executor executor = threadPool.generic();
executor.execute(() -> { executor.execute(() -> {
final String templateName = config.getTemplateName(); final String templateName = config.getTemplateName();
@ -493,12 +507,17 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
onPutTemplateFailure(templateName, e); onPutTemplateFailure(templateName, e);
} }
}, },
client.admin().indices()::putTemplate projectResolver.projectClient(client, projectId).admin().indices()::putTemplate
); );
}); });
} }
private void putComponentTemplate(final String templateName, final ComponentTemplate template, final AtomicBoolean creationCheck) { private void putComponentTemplate(
final ProjectId projectId,
final String templateName,
final ComponentTemplate template,
final AtomicBoolean creationCheck
) {
final Executor executor = threadPool.generic(); final Executor executor = threadPool.generic();
executor.execute(() -> { executor.execute(() -> {
PutComponentTemplateAction.Request request = new PutComponentTemplateAction.Request(templateName).componentTemplate(template); PutComponentTemplateAction.Request request = new PutComponentTemplateAction.Request(templateName).componentTemplate(template);
@ -526,13 +545,14 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
onPutTemplateFailure(templateName, e); onPutTemplateFailure(templateName, e);
} }
}, },
(req, listener) -> client.execute(PutComponentTemplateAction.INSTANCE, req, listener) (req, listener) -> projectResolver.projectClient(client, projectId)
.execute(PutComponentTemplateAction.INSTANCE, req, listener)
); );
}); });
} }
private void putComposableTemplate( private void putComposableTemplate(
ProjectMetadata projectMetadata, final ProjectMetadata project,
final String templateName, final String templateName,
final ComposableIndexTemplate indexTemplate, final ComposableIndexTemplate indexTemplate,
final AtomicBoolean creationCheck final AtomicBoolean creationCheck
@ -551,7 +571,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
public void onResponse(AcknowledgedResponse response) { public void onResponse(AcknowledgedResponse response) {
if (response.isAcknowledged()) { if (response.isAcknowledged()) {
if (applyRolloverAfterTemplateV2Update()) { if (applyRolloverAfterTemplateV2Update()) {
invokeRollover(projectMetadata, templateName, indexTemplate, () -> creationCheck.set((false))); invokeRollover(project, templateName, indexTemplate, () -> creationCheck.set((false)));
} else { } else {
creationCheck.set(false); creationCheck.set(false);
} }
@ -571,32 +591,30 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
onPutTemplateFailure(templateName, e); onPutTemplateFailure(templateName, e);
} }
}, },
(req, listener) -> client.execute(TransportPutComposableIndexTemplateAction.TYPE, req, listener) (req, listener) -> projectResolver.projectClient(client, project.id())
.execute(TransportPutComposableIndexTemplateAction.TYPE, req, listener)
); );
}); });
} }
private void addIndexLifecyclePoliciesIfMissing(ClusterState state) { private void addIndexLifecyclePoliciesIfMissing(ProjectMetadata project) {
if (isDataStreamsLifecycleOnlyMode(clusterService.getSettings())) { if (isDataStreamsLifecycleOnlyMode(clusterService.getSettings())) {
logger.trace("running in data stream lifecycle only mode. skipping the installation of ILM policies."); logger.trace("running in data stream lifecycle only mode. skipping the installation of ILM policies.");
return; return;
} }
final IndexLifecycleMetadata metadata = state.metadata().getProject().custom(IndexLifecycleMetadata.TYPE); final IndexLifecycleMetadata metadata = project.custom(IndexLifecycleMetadata.TYPE);
final Map<String, LifecyclePolicy> policies = metadata != null ? metadata.getPolicies() : Map.of(); final Map<String, LifecyclePolicy> policies = metadata != null ? metadata.getPolicies() : Map.of();
for (LifecyclePolicy policy : getLifecyclePolicies()) { for (LifecyclePolicy policy : getLifecyclePolicies()) {
final AtomicBoolean creationCheck = policyCreationsInProgress.computeIfAbsent( final AtomicBoolean creationCheck = policyCreationsInProgress.computeIfAbsent(project.id(), key -> new ConcurrentHashMap<>())
policy.getName(), .computeIfAbsent(policy.getName(), key -> new AtomicBoolean(false));
key -> new AtomicBoolean(false)
);
if (creationCheck.compareAndSet(false, true)) { if (creationCheck.compareAndSet(false, true)) {
final LifecyclePolicy currentPolicy = policies.get(policy.getName()); final LifecyclePolicy currentPolicy = policies.get(policy.getName());
if (Objects.isNull(currentPolicy)) { if (Objects.isNull(currentPolicy)) {
logger.debug("adding lifecycle policy [{}] for [{}], because it doesn't exist", policy.getName(), getOrigin()); logger.debug("adding lifecycle policy [{}] for [{}], because it doesn't exist", policy.getName(), getOrigin());
putPolicy(policy, creationCheck); putPolicy(project.id(), policy, creationCheck);
} else if (isUpgradeRequired(currentPolicy, policy)) { } else if (isUpgradeRequired(currentPolicy, policy)) {
logger.info("upgrading lifecycle policy [{}] for [{}]", policy.getName(), getOrigin()); logger.info("upgrading lifecycle policy [{}] for [{}]", policy.getName(), getOrigin());
putPolicy(policy, creationCheck); putPolicy(project.id(), policy, creationCheck);
} else { } else {
logger.trace("not adding lifecycle policy [{}] for [{}], because it already exists", policy.getName(), getOrigin()); logger.trace("not adding lifecycle policy [{}] for [{}], because it already exists", policy.getName(), getOrigin());
creationCheck.set(false); creationCheck.set(false);
@ -616,7 +634,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
return false; return false;
} }
private void putPolicy(final LifecyclePolicy policy, final AtomicBoolean creationCheck) { private void putPolicy(ProjectId projectId, final LifecyclePolicy policy, final AtomicBoolean creationCheck) {
final Executor executor = threadPool.generic(); final Executor executor = threadPool.generic();
executor.execute(() -> { executor.execute(() -> {
PutLifecycleRequest request = new PutLifecycleRequest(REGISTRY_ACTION_TIMEOUT, REGISTRY_ACTION_TIMEOUT, policy); PutLifecycleRequest request = new PutLifecycleRequest(REGISTRY_ACTION_TIMEOUT, REGISTRY_ACTION_TIMEOUT, policy);
@ -644,7 +662,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
onPutPolicyFailure(policy, e); onPutPolicyFailure(policy, e);
} }
}, },
(req, listener) -> client.execute(ILMActions.PUT, req, listener) (req, listener) -> projectResolver.projectClient(client, projectId).execute(ILMActions.PUT, req, listener)
); );
}); });
} }
@ -659,16 +677,14 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
})); }));
} }
private void addIngestPipelinesIfMissing(ClusterState state) { private void addIngestPipelinesIfMissing(ProjectMetadata project) {
for (IngestPipelineConfig requiredPipeline : getIngestPipelines()) { for (IngestPipelineConfig requiredPipeline : getIngestPipelines()) {
final AtomicBoolean creationCheck = pipelineCreationsInProgress.computeIfAbsent( final AtomicBoolean creationCheck = pipelineCreationsInProgress.computeIfAbsent(project.id(), key -> new ConcurrentHashMap<>())
requiredPipeline.getId(), .computeIfAbsent(requiredPipeline.getId(), key -> new AtomicBoolean(false));
key -> new AtomicBoolean(false)
);
if (creationCheck.compareAndSet(false, true)) { if (creationCheck.compareAndSet(false, true)) {
List<String> pipelineDependencies = requiredPipeline.getPipelineDependencies(); List<String> pipelineDependencies = requiredPipeline.getPipelineDependencies();
if (pipelineDependencies != null && pipelineDependenciesExist(state, pipelineDependencies) == false) { if (pipelineDependencies != null && pipelineDependenciesExist(project, pipelineDependencies) == false) {
creationCheck.set(false); creationCheck.set(false);
logger.trace( logger.trace(
"not adding ingest pipeline [{}] for [{}] because its dependencies do not exist", "not adding ingest pipeline [{}] for [{}] because its dependencies do not exist",
@ -676,7 +692,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
getOrigin() getOrigin()
); );
} else { } else {
PipelineConfiguration existingPipeline = findInstalledPipeline(state, requiredPipeline.getId()); PipelineConfiguration existingPipeline = findInstalledPipeline(project, requiredPipeline.getId());
if (existingPipeline != null) { if (existingPipeline != null) {
Integer existingPipelineVersion = existingPipeline.getVersion(); Integer existingPipelineVersion = existingPipeline.getVersion();
if (existingPipelineVersion == null || existingPipelineVersion < requiredPipeline.getVersion()) { if (existingPipelineVersion == null || existingPipelineVersion < requiredPipeline.getVersion()) {
@ -687,7 +703,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
existingPipelineVersion, existingPipelineVersion,
requiredPipeline.getVersion() requiredPipeline.getVersion()
); );
putIngestPipeline(requiredPipeline, creationCheck); putIngestPipeline(project.id(), requiredPipeline, creationCheck);
} else { } else {
creationCheck.set(false); creationCheck.set(false);
logger.debug( logger.debug(
@ -702,16 +718,16 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
requiredPipeline.getId(), requiredPipeline.getId(),
getOrigin() getOrigin()
); );
putIngestPipeline(requiredPipeline, creationCheck); putIngestPipeline(project.id(), requiredPipeline, creationCheck);
} }
} }
} }
} }
} }
private static boolean pipelineDependenciesExist(ClusterState state, List<String> dependencies) { private static boolean pipelineDependenciesExist(ProjectMetadata project, List<String> dependencies) {
for (String dependency : dependencies) { for (String dependency : dependencies) {
if (findInstalledPipeline(state, dependency) == null) { if (findInstalledPipeline(project, dependency) == null) {
return false; return false;
} }
} }
@ -719,12 +735,12 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
} }
@Nullable @Nullable
private static PipelineConfiguration findInstalledPipeline(ClusterState state, String pipelineId) { private static PipelineConfiguration findInstalledPipeline(ProjectMetadata project, String pipelineId) {
Optional<IngestMetadata> maybeMeta = Optional.ofNullable(state.metadata().getProject().custom(IngestMetadata.TYPE)); Optional<IngestMetadata> maybeMeta = Optional.ofNullable(project.custom(IngestMetadata.TYPE));
return maybeMeta.map(ingestMetadata -> ingestMetadata.getPipelines().get(pipelineId)).orElse(null); return maybeMeta.map(ingestMetadata -> ingestMetadata.getPipelines().get(pipelineId)).orElse(null);
} }
private void putIngestPipeline(final IngestPipelineConfig pipelineConfig, final AtomicBoolean creationCheck) { private void putIngestPipeline(ProjectId projectId, final IngestPipelineConfig pipelineConfig, final AtomicBoolean creationCheck) {
final Executor executor = threadPool.generic(); final Executor executor = threadPool.generic();
executor.execute(() -> { executor.execute(() -> {
PutPipelineRequest request = new PutPipelineRequest( PutPipelineRequest request = new PutPipelineRequest(
@ -760,7 +776,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
onPutPipelineFailure(pipelineConfig.getId(), e); onPutPipelineFailure(pipelineConfig.getId(), e);
} }
}, },
(req, listener) -> client.execute(PutPipelineTransportAction.TYPE, req, listener) (req, listener) -> projectResolver.projectClient(client, projectId).execute(PutPipelineTransportAction.TYPE, req, listener)
); );
}); });
} }
@ -792,14 +808,14 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
* and then invokes runAfter. * and then invokes runAfter.
*/ */
private void invokeRollover( private void invokeRollover(
final ProjectMetadata projectMetadata, final ProjectMetadata project,
final String templateName, final String templateName,
final ComposableIndexTemplate indexTemplate, final ComposableIndexTemplate indexTemplate,
final Runnable runAfter final Runnable runAfter
) { ) {
final Executor executor = threadPool.generic(); final Executor executor = threadPool.generic();
executor.execute(() -> { executor.execute(() -> {
List<String> rolloverTargets = findRolloverTargetDataStreams(projectMetadata, templateName, indexTemplate); List<String> rolloverTargets = findRolloverTargetDataStreams(project, templateName, indexTemplate);
if (rolloverTargets.isEmpty()) { if (rolloverTargets.isEmpty()) {
runAfter.run(); runAfter.run();
return; return;
@ -810,13 +826,13 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
@Override @Override
public void onResponse(Collection<RolloverResponse> rolloverResponses) { public void onResponse(Collection<RolloverResponse> rolloverResponses) {
runAfter.run(); runAfter.run();
onRolloversBulkResponse(rolloverResponses); onRolloversBulkResponse(project.id(), rolloverResponses);
} }
@Override @Override
public void onFailure(Exception e) { public void onFailure(Exception e) {
runAfter.run(); runAfter.run();
onRolloverFailure(e); onRolloverFailure(project.id(), e);
} }
} }
); );
@ -835,23 +851,28 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
getOrigin(), getOrigin(),
request, request,
groupedActionListener, groupedActionListener,
(req, listener) -> client.execute(RolloverAction.INSTANCE, req, listener) (req, listener) -> projectResolver.projectClient(client, project.id()).execute(RolloverAction.INSTANCE, req, listener)
); );
} }
}); });
} }
void onRolloversBulkResponse(Collection<RolloverResponse> rolloverResponses) { void onRolloversBulkResponse(ProjectId projectId, Collection<RolloverResponse> rolloverResponses) {
for (RolloverResponse rolloverResponse : rolloverResponses) { for (RolloverResponse rolloverResponse : rolloverResponses) {
assert rolloverResponse.isLazy() && rolloverResponse.isRolledOver() == false assert rolloverResponse.isLazy() && rolloverResponse.isRolledOver() == false
: Strings.format("Expected rollover of the [%s] index [%s] to be lazy", getOrigin(), rolloverResponse.getOldIndex()); : Strings.format(
"Expected rollover of the [%s] index [%s] in project [%s] to be lazy",
getOrigin(),
projectId,
rolloverResponse.getOldIndex()
);
} }
} }
void onRolloverFailure(Exception e) { void onRolloverFailure(ProjectId projectId, Exception e) {
logger.error(String.format(Locale.ROOT, "[%s] related rollover failed", getOrigin()), e); logger.error(String.format(Locale.ROOT, "[%s] related rollover failed in project [%s]", getOrigin(), projectId), e);
for (Throwable throwable : e.getSuppressed()) { for (Throwable throwable : e.getSuppressed()) {
logger.error(String.format(Locale.ROOT, "[%s] related rollover failed", getOrigin()), throwable); logger.error(String.format(Locale.ROOT, "[%s] related rollover failed in project [%s]", getOrigin(), projectId), throwable);
} }
} }
@ -863,23 +884,19 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
* as argument * as argument
* </ol> * </ol>
* *
* @param projectMetadata the project metadata from the cluster state * @param project the project metadata from the cluster state
* @param templateName the ID by which the provided index template is being registered * @param templateName the ID by which the provided index template is being registered
* @param indexTemplate the index template for which a data stream is looked up as rollover target * @param indexTemplate the index template for which a data stream is looked up as rollover target
* @return the list of rollover targets matching the provided index template * @return the list of rollover targets matching the provided index template
*/ */
static List<String> findRolloverTargetDataStreams( static List<String> findRolloverTargetDataStreams(ProjectMetadata project, String templateName, ComposableIndexTemplate indexTemplate) {
ProjectMetadata projectMetadata, return project.dataStreams()
String templateName,
ComposableIndexTemplate indexTemplate
) {
return projectMetadata.dataStreams()
.values() .values()
.stream() .stream()
// Limit to checking data streams that match any of the index template's index patterns // Limit to checking data streams that match any of the index template's index patterns
.filter(ds -> indexTemplate.indexPatterns().stream().anyMatch(pattern -> Regex.simpleMatch(pattern, ds.getName()))) .filter(ds -> indexTemplate.indexPatterns().stream().anyMatch(pattern -> Regex.simpleMatch(pattern, ds.getName())))
.filter(ds -> { .filter(ds -> {
final String dsTemplateName = MetadataIndexTemplateService.findV2Template(projectMetadata, ds.getName(), ds.isHidden()); final String dsTemplateName = MetadataIndexTemplateService.findV2Template(project, ds.getName(), ds.isHidden());
if (templateName.equals(dsTemplateName)) { if (templateName.equals(dsTemplateName)) {
return true; return true;
} }
@ -890,7 +907,7 @@ public abstract class IndexTemplateRegistry implements ClusterStateListener {
// //
// Because of the second case, we must check if indexTemplate's priority is greater than the matching // Because of the second case, we must check if indexTemplate's priority is greater than the matching
// index template, in case it would take precedence after installation/update. // index template, in case it would take precedence after installation/update.
final ComposableIndexTemplate dsTemplate = projectMetadata.templatesV2().get(dsTemplateName); final ComposableIndexTemplate dsTemplate = project.templatesV2().get(dsTemplateName);
return dsTemplate == null || indexTemplate.priorityOrZero() > dsTemplate.priorityOrZero(); return dsTemplate == null || indexTemplate.priorityOrZero() > dsTemplate.priorityOrZero();
}) })
.map(DataStream::getName) .map(DataStream::getName)

View file

@ -13,6 +13,7 @@ import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
@ -54,9 +55,10 @@ public abstract class YamlTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
this(nodeSettings, clusterService, threadPool, client, xContentRegistry, ignored -> true); this(nodeSettings, clusterService, threadPool, client, xContentRegistry, ignored -> true, projectResolver);
} }
@SuppressWarnings({ "unchecked", "this-escape" }) @SuppressWarnings({ "unchecked", "this-escape" })
@ -66,9 +68,10 @@ public abstract class YamlTemplateRegistry extends IndexTemplateRegistry {
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry, NamedXContentRegistry xContentRegistry,
Predicate<String> templateFilter Predicate<String> templateFilter,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
try { try {
final Map<String, Object> resources = XContentHelper.convertToMap( final Map<String, Object> resources = XContentHelper.convertToMap(
YamlXContent.yamlXContent, YamlXContent.yamlXContent,

View file

@ -13,7 +13,6 @@ import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.ActionType; import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.admin.indices.rollover.RolloverAction; import org.elasticsearch.action.admin.indices.rollover.RolloverAction;
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest; import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
import org.elasticsearch.action.admin.indices.template.put.PutComponentTemplateAction; import org.elasticsearch.action.admin.indices.template.put.PutComponentTemplateAction;
import org.elasticsearch.action.admin.indices.template.put.TransportPutComposableIndexTemplateAction; import org.elasticsearch.action.admin.indices.template.put.TransportPutComposableIndexTemplateAction;
import org.elasticsearch.action.ingest.PutPipelineRequest; import org.elasticsearch.action.ingest.PutPipelineRequest;
@ -27,17 +26,20 @@ import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.metadata.DataStreamTestHelper; import org.elasticsearch.cluster.metadata.DataStreamTestHelper;
import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.metadata.ProjectId;
import org.elasticsearch.cluster.metadata.ProjectMetadata;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.TriFunction;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.core.Strings; import org.elasticsearch.core.Strings;
import org.elasticsearch.index.Index; import org.elasticsearch.index.Index;
import org.elasticsearch.ingest.IngestMetadata; import org.elasticsearch.ingest.IngestMetadata;
import org.elasticsearch.ingest.PipelineConfiguration; import org.elasticsearch.ingest.PipelineConfiguration;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.test.ClusterServiceUtils; import org.elasticsearch.test.ClusterServiceUtils;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.client.NoOpClient; import org.elasticsearch.test.client.NoOpClient;
@ -60,14 +62,13 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import java.io.IOException; import java.io.IOException;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
@ -83,6 +84,9 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
public class IndexTemplateRegistryTests extends ESTestCase { public class IndexTemplateRegistryTests extends ESTestCase {
private final ProjectId projectId = randomProjectIdOrDefault();
private TestRegistryWithCustomPlugin registry; private TestRegistryWithCustomPlugin registry;
private ClusterService clusterService; private ClusterService clusterService;
private ThreadPool threadPool; private ThreadPool threadPool;
@ -93,7 +97,14 @@ public class IndexTemplateRegistryTests extends ESTestCase {
threadPool = new TestThreadPool(this.getClass().getName()); threadPool = new TestThreadPool(this.getClass().getName());
client = new VerifyingClient(threadPool); client = new VerifyingClient(threadPool);
clusterService = ClusterServiceUtils.createClusterService(threadPool); clusterService = ClusterServiceUtils.createClusterService(threadPool);
registry = new TestRegistryWithCustomPlugin(Settings.EMPTY, clusterService, threadPool, client, NamedXContentRegistry.EMPTY); registry = new TestRegistryWithCustomPlugin(
Settings.EMPTY,
clusterService,
threadPool,
client,
NamedXContentRegistry.EMPTY,
TestProjectResolvers.usingRequestHeader(threadPool.getThreadContext())
);
} }
@After @After
@ -107,9 +118,10 @@ public class IndexTemplateRegistryTests extends ESTestCase {
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build();
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == PutPipelineTransportAction.TYPE) { if (action == PutPipelineTransportAction.TYPE) {
final var calledTimes = calledTimesMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
assertPutPipelineAction(calledTimes, action, request, listener, "custom-plugin-final_pipeline"); assertPutPipelineAction(calledTimes, action, request, listener, "custom-plugin-final_pipeline");
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
} else if (action == ILMActions.PUT) { } else if (action == ILMActions.PUT) {
@ -125,16 +137,17 @@ public class IndexTemplateRegistryTests extends ESTestCase {
ClusterChangedEvent event = createClusterChangedEvent(Collections.emptyMap(), nodes); ClusterChangedEvent event = createClusterChangedEvent(Collections.emptyMap(), nodes);
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(1))); assertCalledTimes(calledTimesMap, event, 1);
} }
public void testThatDependentPipelinesAreAddedIfDependenciesExist() throws Exception { public void testThatDependentPipelinesAreAddedIfDependenciesExist() throws Exception {
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build();
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == PutPipelineTransportAction.TYPE) { if (action == PutPipelineTransportAction.TYPE) {
final var calledTimes = calledTimesMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
assertPutPipelineAction(calledTimes, action, request, listener, "custom-plugin-default_pipeline"); assertPutPipelineAction(calledTimes, action, request, listener, "custom-plugin-default_pipeline");
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
} else if (action == ILMActions.PUT) { } else if (action == ILMActions.PUT) {
@ -155,16 +168,17 @@ public class IndexTemplateRegistryTests extends ESTestCase {
nodes nodes
); );
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(1))); assertCalledTimes(calledTimesMap, event, 1);
} }
public void testThatTemplateIsAddedIfAllDependenciesExist() throws Exception { public void testThatTemplateIsAddedIfAllDependenciesExist() throws Exception {
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build();
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action instanceof PutComponentTemplateAction) { if (action instanceof PutComponentTemplateAction) {
final var calledTimes = calledTimesMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
assertPutComponentTemplate(calledTimes, action, request, listener); assertPutComponentTemplate(calledTimes, action, request, listener);
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
} else if (action == ILMActions.PUT) { } else if (action == ILMActions.PUT) {
@ -184,16 +198,17 @@ public class IndexTemplateRegistryTests extends ESTestCase {
nodes nodes
); );
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(1))); assertCalledTimes(calledTimesMap, event, 1);
} }
public void testThatTemplateIsNotAddedIfNotAllDependenciesExist() throws Exception { public void testThatTemplateIsNotAddedIfNotAllDependenciesExist() throws Exception {
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build();
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == PutPipelineTransportAction.TYPE) { if (action == PutPipelineTransportAction.TYPE) {
final var calledTimes = calledTimesMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
assertPutPipelineAction(calledTimes, action, request, listener, "custom-plugin-default_pipeline"); assertPutPipelineAction(calledTimes, action, request, listener, "custom-plugin-default_pipeline");
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
} else if (action == ILMActions.PUT) { } else if (action == ILMActions.PUT) {
@ -213,16 +228,17 @@ public class IndexTemplateRegistryTests extends ESTestCase {
nodes nodes
); );
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(1))); assertCalledTimes(calledTimesMap, event, 1);
} }
public void testThatComposableTemplateIsAddedIfDependenciesExist() throws Exception { public void testThatComposableTemplateIsAddedIfDependenciesExist() throws Exception {
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build();
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == TransportPutComposableIndexTemplateAction.TYPE) { if (action == TransportPutComposableIndexTemplateAction.TYPE) {
final var calledTimes = calledTimesMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
assertPutComposableIndexTemplateAction(calledTimes, action, request, listener); assertPutComposableIndexTemplateAction(calledTimes, action, request, listener);
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
} else if (action == ILMActions.PUT) { } else if (action == ILMActions.PUT) {
@ -240,16 +256,17 @@ public class IndexTemplateRegistryTests extends ESTestCase {
ClusterChangedEvent event = createClusterChangedEvent(Collections.singletonMap("custom-plugin-settings", 3), nodes); ClusterChangedEvent event = createClusterChangedEvent(Collections.singletonMap("custom-plugin-settings", 3), nodes);
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(1))); assertCalledTimes(calledTimesMap, event, 1);
} }
public void testThatComposableTemplateIsAddedIfDependenciesHaveRightVersion() throws Exception { public void testThatComposableTemplateIsAddedIfDependenciesHaveRightVersion() throws Exception {
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build();
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == TransportPutComposableIndexTemplateAction.TYPE) { if (action == TransportPutComposableIndexTemplateAction.TYPE) {
final var calledTimes = calledTimesMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
assertPutComposableIndexTemplateAction(calledTimes, action, request, listener); assertPutComposableIndexTemplateAction(calledTimes, action, request, listener);
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
} else if (action instanceof PutComponentTemplateAction) { } else if (action instanceof PutComponentTemplateAction) {
@ -272,26 +289,27 @@ public class IndexTemplateRegistryTests extends ESTestCase {
// to their version // to their version
ClusterChangedEvent event = createClusterChangedEvent(Collections.singletonMap("custom-plugin-settings", 2), nodes); ClusterChangedEvent event = createClusterChangedEvent(Collections.singletonMap("custom-plugin-settings", 2), nodes);
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(1))); assertCalledTimes(calledTimesMap, event, 1);
// when a registry requires rollovers after index template updates, the upgrade should occur only if the dependencies are have // when a registry requires rollovers after index template updates, the upgrade should occur only if the dependencies are have
// the required version // the required version
registry.setApplyRollover(true); registry.setApplyRollover(true);
calledTimes.set(0); calledTimesMap.values().forEach(calledTimes -> calledTimes.set(0));
registry.clusterChanged(event); registry.clusterChanged(event);
Thread.sleep(100L); Thread.sleep(100L);
assertThat(calledTimes.get(), equalTo(0)); assertCalledTimes(calledTimesMap, event, 0);
event = createClusterChangedEvent(Collections.singletonMap("custom-plugin-settings", 3), nodes); event = createClusterChangedEvent(Collections.singletonMap("custom-plugin-settings", 3), nodes);
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(1))); assertCalledTimes(calledTimesMap, event, 1);
} }
public void testThatTemplatesAreUpgradedWhenNeeded() throws Exception { public void testThatTemplatesAreUpgradedWhenNeeded() throws Exception {
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build();
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
final var calledTimes = calledTimesMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
if (action == PutPipelineTransportAction.TYPE) { if (action == PutPipelineTransportAction.TYPE) {
assertPutPipelineAction( assertPutPipelineAction(
calledTimes, calledTimes,
@ -324,7 +342,7 @@ public class IndexTemplateRegistryTests extends ESTestCase {
nodes nodes
); );
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(4))); assertCalledTimes(calledTimesMap, event, 4);
} }
public void testAutomaticRollover() throws Exception { public void testAutomaticRollover() throws Exception {
@ -338,11 +356,12 @@ public class IndexTemplateRegistryTests extends ESTestCase {
nodes nodes
); );
Map<String, ComposableIndexTemplate> composableTemplateConfigs = registry.getComposableTemplateConfigs(); Map<String, ComposableIndexTemplate> composableTemplateConfigs = registry.getComposableTemplateConfigs();
final var metadataBuilder = Metadata.builder(state.metadata());
for (Map.Entry<String, ComposableIndexTemplate> entry : composableTemplateConfigs.entrySet()) { for (Map.Entry<String, ComposableIndexTemplate> entry : composableTemplateConfigs.entrySet()) {
ComposableIndexTemplate template = entry.getValue(); ComposableIndexTemplate template = entry.getValue();
state = ClusterState.builder(state) for (var project : state.metadata().projects().values()) {
.metadata( metadataBuilder.put(
Metadata.builder(Objects.requireNonNull(state).metadata()) metadataBuilder.getProject(project.id())
.put( .put(
entry.getKey(), entry.getKey(),
ComposableIndexTemplate.builder() ComposableIndexTemplate.builder()
@ -355,84 +374,100 @@ public class IndexTemplateRegistryTests extends ESTestCase {
.dataStreamTemplate(template.getDataStreamTemplate()) .dataStreamTemplate(template.getDataStreamTemplate())
.build() .build()
) )
) );
.build(); }
} }
state = ClusterState.builder(state) for (var project : state.metadata().projects().values()) {
.metadata( metadataBuilder.put(
Metadata.builder(Objects.requireNonNull(state).metadata()) metadataBuilder.getProject(project.id())
.put(DataStreamTestHelper.newInstance("logs-my_app-1", Collections.singletonList(new Index(".ds-ds1-000001", "ds1i")))) .put(DataStreamTestHelper.newInstance("logs-my_app-1", Collections.singletonList(new Index(".ds-ds1-000001", "ds1i"))))
.put(DataStreamTestHelper.newInstance("logs-my_app-2", Collections.singletonList(new Index(".ds-ds2-000001", "ds2i")))) .put(DataStreamTestHelper.newInstance("logs-my_app-2", Collections.singletonList(new Index(".ds-ds2-000001", "ds2i"))))
.put( .put(
DataStreamTestHelper.newInstance("traces-my_app-1", Collections.singletonList(new Index(".ds-ds3-000001", "ds3i"))) DataStreamTestHelper.newInstance("traces-my_app-1", Collections.singletonList(new Index(".ds-ds3-000001", "ds3i")))
) )
) );
.build(); }
state = ClusterState.builder(state).metadata(metadataBuilder).build();
ClusterChangedEvent event = createClusterChangedEvent(nodes, state); ClusterChangedEvent event = createClusterChangedEvent(nodes, state);
AtomicInteger rolloverCounter = new AtomicInteger(0); Map<ProjectId, AtomicInteger> rolloverCounterMap = new ConcurrentHashMap<>();
AtomicInteger putIndexTemplateCounter = new AtomicInteger(0); Map<ProjectId, AtomicInteger> putIndexTemplateCounterMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action instanceof RolloverAction) { if (action instanceof RolloverAction) {
final var rolloverCounter = rolloverCounterMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
rolloverCounter.incrementAndGet(); rolloverCounter.incrementAndGet();
RolloverRequest rolloverRequest = ((RolloverRequest) request); RolloverRequest rolloverRequest = ((RolloverRequest) request);
assertThat(rolloverRequest.getRolloverTarget(), startsWith("logs-my_app-")); assertThat(rolloverRequest.getRolloverTarget(), startsWith("logs-my_app-"));
assertThat(rolloverRequest.isLazy(), equalTo(true)); assertThat(rolloverRequest.isLazy(), equalTo(true));
} else if (action == TransportPutComposableIndexTemplateAction.TYPE) { } else if (action == TransportPutComposableIndexTemplateAction.TYPE) {
final var putIndexTemplateCounter = putIndexTemplateCounterMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
putIndexTemplateCounter.incrementAndGet(); putIndexTemplateCounter.incrementAndGet();
} }
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
}); });
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(putIndexTemplateCounter.get(), equalTo(1))); assertCalledTimes(putIndexTemplateCounterMap, event, 1);
// no rollover on upgrade because the test registry doesn't support automatic rollover by default // no rollover on upgrade because the test registry doesn't support automatic rollover by default
Thread.sleep(100L); Thread.sleep(100L);
assertThat(rolloverCounter.get(), equalTo(0)); assertCalledTimes(rolloverCounterMap, event, 0);
// test successful rollovers // test successful rollovers
registry.setApplyRollover(true); registry.setApplyRollover(true);
putIndexTemplateCounter.set(0); putIndexTemplateCounterMap.values().forEach(calledTimes -> calledTimes.set(0));
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(putIndexTemplateCounter.get(), equalTo(1))); assertCalledTimes(putIndexTemplateCounterMap, event, 1);
assertBusy(() -> assertThat(rolloverCounter.get(), equalTo(2))); assertCalledTimes(rolloverCounterMap, event, 2);
AtomicReference<Collection<RolloverResponse>> rolloverResponsesRef = registry.getRolloverResponses(); var rolloverResponsesRef = registry.getRolloverResponses();
assertBusy(() -> assertNotNull(rolloverResponsesRef.get())); var projectIds = state.metadata().projects().keySet();
assertThat(rolloverResponsesRef.get(), hasSize(2)); assertBusy(() -> {
assertThat(rolloverResponsesRef.keySet(), equalTo(projectIds));
for (var rolloverResponses : rolloverResponsesRef.values()) {
assertNotNull(rolloverResponses.get());
assertThat(rolloverResponses.get(), hasSize(2));
}
});
// test again, to verify that the per-index-template creation lock gets released for reuse // test again, to verify that the per-index-template creation lock gets released for reuse
putIndexTemplateCounter.set(0); putIndexTemplateCounterMap.values().forEach(calledTimes -> calledTimes.set(0));
rolloverCounter.set(0); rolloverCounterMap.values().forEach(calledTimes -> calledTimes.set(0));
rolloverResponsesRef.set(Collections.emptySet()); rolloverResponsesRef.values().forEach(v -> v.set(Set.of()));
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(putIndexTemplateCounter.get(), equalTo(1))); assertCalledTimes(putIndexTemplateCounterMap, event, 1);
assertBusy(() -> assertThat(rolloverCounter.get(), equalTo(2))); assertCalledTimes(rolloverCounterMap, event, 2);
assertBusy(() -> assertThat(rolloverResponsesRef.get(), hasSize(2))); assertBusy(() -> rolloverResponsesRef.values().forEach(v -> assertThat(v.get(), hasSize(2))));
// test rollover failures // test rollover failures
putIndexTemplateCounter.set(0); putIndexTemplateCounterMap.values().forEach(calledTimes -> calledTimes.set(0));
rolloverCounter.set(0); rolloverCounterMap.values().forEach(calledTimes -> calledTimes.set(0));
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action instanceof RolloverAction) { if (action instanceof RolloverAction) {
final var rolloverCounter = rolloverCounterMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
rolloverCounter.incrementAndGet(); rolloverCounter.incrementAndGet();
RolloverRequest rolloverRequest = ((RolloverRequest) request); RolloverRequest rolloverRequest = ((RolloverRequest) request);
assertThat(rolloverRequest.getRolloverTarget(), startsWith("logs-my_app-")); assertThat(rolloverRequest.getRolloverTarget(), startsWith("logs-my_app-"));
throw new RuntimeException("Failed to rollover " + rolloverRequest.getRolloverTarget()); throw new RuntimeException("Failed to rollover " + rolloverRequest.getRolloverTarget());
} else if (action == TransportPutComposableIndexTemplateAction.TYPE) { } else if (action == TransportPutComposableIndexTemplateAction.TYPE) {
final var putIndexTemplateCounter = putIndexTemplateCounterMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
putIndexTemplateCounter.incrementAndGet(); putIndexTemplateCounter.incrementAndGet();
} }
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
}); });
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(putIndexTemplateCounter.get(), equalTo(1))); assertCalledTimes(putIndexTemplateCounterMap, event, 1);
assertBusy(() -> assertThat(rolloverCounter.get(), equalTo(2))); assertCalledTimes(rolloverCounterMap, event, 2);
AtomicReference<Exception> rolloverFailureRef = registry.getRolloverFailure(); var rolloverFailureRefMap = registry.getRolloverFailure();
assertBusy(() -> assertNotNull(rolloverFailureRef.get())); assertBusy(() -> {
Exception rolloverFailure = rolloverFailureRef.get(); assertThat(rolloverFailureRefMap.keySet(), equalTo(projectIds));
assertThat(rolloverFailure.getMessage(), startsWith("Failed to rollover logs-my_app-")); rolloverFailureRefMap.values().forEach(rolloverFailureRef -> {
Throwable[] suppressed = rolloverFailure.getSuppressed(); assertNotNull(rolloverFailureRef.get());
assertThat(suppressed.length, equalTo(1)); Exception rolloverFailure = rolloverFailureRef.get();
assertThat(suppressed[0].getMessage(), startsWith("Failed to rollover logs-my_app-")); assertThat(rolloverFailure.getMessage(), startsWith("Failed to rollover logs-my_app-"));
Throwable[] suppressed = rolloverFailure.getSuppressed();
assertThat(suppressed.length, equalTo(1));
assertThat(suppressed[0].getMessage(), startsWith("Failed to rollover logs-my_app-"));
});
});
} }
public void testRolloverForFreshInstalledIndexTemplate() throws Exception { public void testRolloverForFreshInstalledIndexTemplate() throws Exception {
@ -445,26 +480,30 @@ public class IndexTemplateRegistryTests extends ESTestCase {
Map.of("custom-plugin-default_pipeline", 3, "custom-plugin-final_pipeline", 3), Map.of("custom-plugin-default_pipeline", 3, "custom-plugin-final_pipeline", 3),
nodes nodes
); );
state = ClusterState.builder(state) final var metadataBuilder = Metadata.builder(state.metadata());
.metadata( for (var project : state.metadata().projects().values()) {
Metadata.builder(Objects.requireNonNull(state).metadata()) metadataBuilder.put(
metadataBuilder.getProject(project.id())
.put(DataStreamTestHelper.newInstance("logs-my_app-1", Collections.singletonList(new Index(".ds-ds1-000001", "ds1i")))) .put(DataStreamTestHelper.newInstance("logs-my_app-1", Collections.singletonList(new Index(".ds-ds1-000001", "ds1i"))))
.put(DataStreamTestHelper.newInstance("logs-my_app-2", Collections.singletonList(new Index(".ds-ds2-000001", "ds2i")))) .put(DataStreamTestHelper.newInstance("logs-my_app-2", Collections.singletonList(new Index(".ds-ds2-000001", "ds2i"))))
.put( .put(
DataStreamTestHelper.newInstance("traces-my_app-1", Collections.singletonList(new Index(".ds-ds3-000001", "ds3i"))) DataStreamTestHelper.newInstance("traces-my_app-1", Collections.singletonList(new Index(".ds-ds3-000001", "ds3i")))
) )
) );
.build(); }
state = ClusterState.builder(state).metadata(metadataBuilder).build();
ClusterChangedEvent event = createClusterChangedEvent(nodes, state); ClusterChangedEvent event = createClusterChangedEvent(nodes, state);
AtomicInteger rolloverCounter = new AtomicInteger(0); Map<ProjectId, AtomicInteger> rolloverCounterMap = new ConcurrentHashMap<>();
AtomicInteger putIndexTemplateCounter = new AtomicInteger(0); Map<ProjectId, AtomicInteger> putIndexTemplateCounterMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action instanceof RolloverAction) { if (action instanceof RolloverAction) {
final var rolloverCounter = rolloverCounterMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
rolloverCounter.incrementAndGet(); rolloverCounter.incrementAndGet();
RolloverRequest rolloverRequest = ((RolloverRequest) request); RolloverRequest rolloverRequest = ((RolloverRequest) request);
assertThat(rolloverRequest.getRolloverTarget(), startsWith("logs-my_app-")); assertThat(rolloverRequest.getRolloverTarget(), startsWith("logs-my_app-"));
} else if (action == TransportPutComposableIndexTemplateAction.TYPE) { } else if (action == TransportPutComposableIndexTemplateAction.TYPE) {
final var putIndexTemplateCounter = putIndexTemplateCounterMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
putIndexTemplateCounter.incrementAndGet(); putIndexTemplateCounter.incrementAndGet();
} }
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
@ -472,18 +511,18 @@ public class IndexTemplateRegistryTests extends ESTestCase {
registry.setApplyRollover(true); registry.setApplyRollover(true);
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(putIndexTemplateCounter.get(), equalTo(1))); assertCalledTimes(putIndexTemplateCounterMap, event, 1);
// rollover should be triggered even for the first installation, since the template // rollover should be triggered even for the first installation, since the template
// may now take precedence over a data stream's existing index template // may now take precedence over a data stream's existing index template
assertBusy(() -> assertThat(rolloverCounter.get(), equalTo(2))); assertCalledTimes(rolloverCounterMap, event, 2);
} }
public void testThatTemplatesAreNotUpgradedWhenNotNeeded() throws Exception { public void testThatTemplatesAreNotUpgradedWhenNotNeeded() throws Exception {
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build();
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == TransportPutComposableIndexTemplateAction.TYPE) { if (action == TransportPutComposableIndexTemplateAction.TYPE) {
// ignore this // ignore this
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
@ -503,19 +542,20 @@ public class IndexTemplateRegistryTests extends ESTestCase {
nodes nodes
); );
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(0))); assertCalledTimes(calledTimesMap, event, 0);
} }
public void testThatNonExistingPoliciesAreAddedImmediately() throws Exception { public void testThatNonExistingPoliciesAreAddedImmediately() throws Exception {
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");
DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build(); DiscoveryNodes nodes = DiscoveryNodes.builder().localNodeId("node").masterNodeId("node").add(node).build();
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == TransportPutComposableIndexTemplateAction.TYPE) { if (action == TransportPutComposableIndexTemplateAction.TYPE) {
// ignore this // ignore this
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
} else if (action == ILMActions.PUT) { } else if (action == ILMActions.PUT) {
final var calledTimes = calledTimesMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
assertPutLifecycleAction(calledTimes, action, request, listener); assertPutLifecycleAction(calledTimes, action, request, listener);
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
} else { } else {
@ -531,7 +571,7 @@ public class IndexTemplateRegistryTests extends ESTestCase {
nodes nodes
); );
registry.clusterChanged(event); registry.clusterChanged(event);
assertBusy(() -> assertThat(calledTimes.get(), equalTo(registry.getLifecyclePolicies().size()))); assertCalledTimes(calledTimesMap, event, registry.getLifecyclePolicies().size());
} }
public void testPolicyAlreadyExists() { public void testPolicyAlreadyExists() {
@ -543,7 +583,7 @@ public class IndexTemplateRegistryTests extends ESTestCase {
assertThat(policies, hasSize(1)); assertThat(policies, hasSize(1));
policies.forEach(p -> policyMap.put(p.getName(), p)); policies.forEach(p -> policyMap.put(p.getName(), p));
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == TransportPutComposableIndexTemplateAction.TYPE) { if (action == TransportPutComposableIndexTemplateAction.TYPE) {
// ignore this // ignore this
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
@ -575,7 +615,7 @@ public class IndexTemplateRegistryTests extends ESTestCase {
assertThat(policies, hasSize(1)); assertThat(policies, hasSize(1));
policies.forEach(p -> policyMap.put(p.getName(), p)); policies.forEach(p -> policyMap.put(p.getName(), p));
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == TransportPutComposableIndexTemplateAction.TYPE) { if (action == TransportPutComposableIndexTemplateAction.TYPE) {
// ignore this // ignore this
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
@ -627,12 +667,13 @@ public class IndexTemplateRegistryTests extends ESTestCase {
assertThat(policies, hasSize(1)); assertThat(policies, hasSize(1));
policies.forEach(p -> policyMap.put(p.getName(), p)); policies.forEach(p -> policyMap.put(p.getName(), p));
AtomicInteger calledTimes = new AtomicInteger(0); Map<ProjectId, AtomicInteger> calledTimesMap = new ConcurrentHashMap<>();
client.setVerifier((action, request, listener) -> { client.setVerifier((projectId, action, request, listener) -> {
if (action == TransportPutComposableIndexTemplateAction.TYPE) { if (action == TransportPutComposableIndexTemplateAction.TYPE) {
// ignore this // ignore this
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
} else if (action == ILMActions.PUT) { } else if (action == ILMActions.PUT) {
final var calledTimes = calledTimesMap.computeIfAbsent(projectId, k -> new AtomicInteger(0));
assertPutLifecycleAction(calledTimes, action, request, listener); assertPutLifecycleAction(calledTimes, action, request, listener);
return AcknowledgedResponse.TRUE; return AcknowledgedResponse.TRUE;
@ -669,7 +710,7 @@ public class IndexTemplateRegistryTests extends ESTestCase {
); );
registry.clusterChanged(event); registry.clusterChanged(event);
// we've changed one policy that should be upgraded // we've changed one policy that should be upgraded
assertBusy(() -> assertThat(calledTimes.get(), equalTo(1))); assertCalledTimes(calledTimesMap, event, 1);
} }
} }
@ -749,6 +790,18 @@ public class IndexTemplateRegistryTests extends ESTestCase {
calledTimes.incrementAndGet(); calledTimes.incrementAndGet();
} }
private static void assertCalledTimes(Map<ProjectId, AtomicInteger> calledTimesMap, ClusterChangedEvent event, int expectedTimes)
throws Exception {
assertBusy(() -> {
if (expectedTimes > 0) {
assertThat(calledTimesMap.keySet(), equalTo(event.state().metadata().projects().keySet()));
}
for (var calledTimes : calledTimesMap.values()) {
assertThat(calledTimes.get(), equalTo(expectedTimes));
}
});
}
private ClusterChangedEvent createClusterChangedEvent(Map<String, Integer> existingTemplates, DiscoveryNodes nodes) { private ClusterChangedEvent createClusterChangedEvent(Map<String, Integer> existingTemplates, DiscoveryNodes nodes) {
return createClusterChangedEvent(existingTemplates, Collections.emptyMap(), Collections.emptyMap(), nodes); return createClusterChangedEvent(existingTemplates, Collections.emptyMap(), Collections.emptyMap(), nodes);
} }
@ -810,10 +863,21 @@ public class IndexTemplateRegistryTests extends ESTestCase {
return ClusterState.builder(new ClusterName("test")) return ClusterState.builder(new ClusterName("test"))
.metadata( .metadata(
Metadata.builder() Metadata.builder()
.componentTemplates(componentTemplates)
.transientSettings(Settings.EMPTY) .transientSettings(Settings.EMPTY)
.putCustom(IndexLifecycleMetadata.TYPE, ilmMeta) .put(
.putCustom(IngestMetadata.TYPE, ingestMetadata) ProjectMetadata.builder(Metadata.DEFAULT_PROJECT_ID)
.componentTemplates(componentTemplates)
.putCustom(IndexLifecycleMetadata.TYPE, ilmMeta)
.putCustom(IngestMetadata.TYPE, ingestMetadata)
.build()
)
.put(
ProjectMetadata.builder(projectId)
.componentTemplates(componentTemplates)
.putCustom(IndexLifecycleMetadata.TYPE, ilmMeta)
.putCustom(IngestMetadata.TYPE, ingestMetadata)
.build()
)
.build() .build()
) )
.blocks(new ClusterBlocks.Builder().build()) .blocks(new ClusterBlocks.Builder().build())
@ -872,7 +936,7 @@ public class IndexTemplateRegistryTests extends ESTestCase {
*/ */
public static class VerifyingClient extends NoOpClient { public static class VerifyingClient extends NoOpClient {
private TriFunction<ActionType<?>, ActionRequest, ActionListener<?>, ActionResponse> verifier = (a, r, l) -> { private Verifier verifier = (p, a, r, l) -> {
fail("verifier not set"); fail("verifier not set");
return null; return null;
}; };
@ -889,15 +953,22 @@ public class IndexTemplateRegistryTests extends ESTestCase {
ActionListener<Response> listener ActionListener<Response> listener
) { ) {
try { try {
listener.onResponse((Response) verifier.apply(action, request, listener)); final ProjectId projectId = ProjectId.fromId(
threadPool().getThreadContext().getHeader(Task.X_ELASTIC_PROJECT_ID_HTTP_HEADER)
);
listener.onResponse((Response) verifier.verify(projectId, action, request, listener));
} catch (Exception e) { } catch (Exception e) {
listener.onFailure(e); listener.onFailure(e);
} }
} }
public VerifyingClient setVerifier(TriFunction<ActionType<?>, ActionRequest, ActionListener<?>, ActionResponse> verifier) { public VerifyingClient setVerifier(Verifier verifier) {
this.verifier = verifier; this.verifier = verifier;
return this; return this;
} }
} }
private interface Verifier {
ActionResponse verify(ProjectId projectId, ActionType<?> action, ActionRequest request, ActionListener<?> listener);
}
} }

View file

@ -11,6 +11,8 @@ import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.metadata.ProjectId;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -24,6 +26,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -35,17 +38,21 @@ class TestRegistryWithCustomPlugin extends IndexTemplateRegistry {
private final AtomicBoolean policyUpgradeRequired = new AtomicBoolean(false); private final AtomicBoolean policyUpgradeRequired = new AtomicBoolean(false);
private final AtomicBoolean applyRollover = new AtomicBoolean(false); private final AtomicBoolean applyRollover = new AtomicBoolean(false);
private final AtomicReference<Collection<RolloverResponse>> rolloverResponses = new AtomicReference<>(); private final Map<ProjectId, AtomicReference<Collection<RolloverResponse>>> rolloverResponses = new ConcurrentHashMap<>();
private final AtomicReference<Exception> rolloverFailure = new AtomicReference<>(); private final Map<ProjectId, AtomicReference<Exception>> rolloverFailure = new ConcurrentHashMap<>();
private final ThreadPool threadPool;
TestRegistryWithCustomPlugin( TestRegistryWithCustomPlugin(
Settings nodeSettings, Settings nodeSettings,
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
this.threadPool = threadPool;
} }
@Override @Override
@ -127,20 +134,20 @@ class TestRegistryWithCustomPlugin extends IndexTemplateRegistry {
} }
@Override @Override
void onRolloversBulkResponse(Collection<RolloverResponse> rolloverResponses) { void onRolloversBulkResponse(ProjectId projectId, Collection<RolloverResponse> rolloverResponses) {
this.rolloverResponses.set(rolloverResponses); this.rolloverResponses.computeIfAbsent(projectId, k -> new AtomicReference<>()).set(rolloverResponses);
} }
public AtomicReference<Collection<RolloverResponse>> getRolloverResponses() { public Map<ProjectId, AtomicReference<Collection<RolloverResponse>>> getRolloverResponses() {
return rolloverResponses; return rolloverResponses;
} }
@Override @Override
void onRolloverFailure(Exception e) { void onRolloverFailure(ProjectId projectId, Exception e) {
rolloverFailure.set(e); rolloverFailure.computeIfAbsent(projectId, k -> new AtomicReference<>()).set(e);
} }
public AtomicReference<Exception> getRolloverFailure() { public Map<ProjectId, AtomicReference<Exception>> getRolloverFailure() {
return rolloverFailure; return rolloverFailure;
} }

View file

@ -85,7 +85,8 @@ public class Deprecation extends Plugin implements ActionPlugin {
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
templateRegistry.initialize(); templateRegistry.initialize();

View file

@ -10,6 +10,7 @@ package org.elasticsearch.xpack.deprecation.logging;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -49,9 +50,10 @@ public class DeprecationIndexingTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
private static final Map<String, ComponentTemplate> COMPONENT_TEMPLATE_CONFIGS; private static final Map<String, ComponentTemplate> COMPONENT_TEMPLATE_CONFIGS;

View file

@ -469,7 +469,8 @@ public class EnterpriseSearch extends Plugin implements ActionPlugin, SystemInde
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
analyticsTemplateRegistry.initialize(); analyticsTemplateRegistry.initialize();
@ -478,7 +479,8 @@ public class EnterpriseSearch extends Plugin implements ActionPlugin, SystemInde
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
connectorTemplateRegistry.initialize(); connectorTemplateRegistry.initialize();

View file

@ -9,6 +9,7 @@ package org.elasticsearch.xpack.application.analytics;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.core.UpdateForV10; import org.elasticsearch.core.UpdateForV10;
@ -105,9 +106,10 @@ public class AnalyticsTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(Settings.EMPTY, clusterService, threadPool, client, xContentRegistry); super(Settings.EMPTY, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
@Override @Override

View file

@ -10,6 +10,7 @@ package org.elasticsearch.xpack.application.connector;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -144,9 +145,10 @@ public class ConnectorTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(Settings.EMPTY, clusterService, threadPool, client, xContentRegistry); super(Settings.EMPTY, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
@Override @Override

View file

@ -25,6 +25,7 @@ import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.TriFunction; import org.elasticsearch.common.TriFunction;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
@ -75,7 +76,13 @@ public class AnalyticsTemplateRegistryTests extends ESTestCase {
threadPool = new TestThreadPool(this.getClass().getName()); threadPool = new TestThreadPool(this.getClass().getName());
client = new VerifyingClient(threadPool); client = new VerifyingClient(threadPool);
ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
registry = new AnalyticsTemplateRegistry(clusterService, threadPool, client, NamedXContentRegistry.EMPTY); registry = new AnalyticsTemplateRegistry(
clusterService,
threadPool,
client,
NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
);
} }
@After @After

View file

@ -25,6 +25,7 @@ import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.TriFunction; import org.elasticsearch.common.TriFunction;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
@ -78,7 +79,13 @@ public class ConnectorTemplateRegistryTests extends ESTestCase {
threadPool = new TestThreadPool(this.getClass().getName()); threadPool = new TestThreadPool(this.getClass().getName());
client = new VerifyingClient(threadPool); client = new VerifyingClient(threadPool);
ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
registry = new ConnectorTemplateRegistry(clusterService, threadPool, client, NamedXContentRegistry.EMPTY); registry = new ConnectorTemplateRegistry(
clusterService,
threadPool,
client,
NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
);
} }
@After @After

View file

@ -95,7 +95,8 @@ public class Fleet extends Plugin implements SystemIndexPlugin {
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
registry.initialize(); registry.initialize();
return List.of(); return List.of();

View file

@ -9,6 +9,7 @@ package org.elasticsearch.xpack.fleet;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -67,9 +68,10 @@ public class FleetTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
@Override @Override

View file

@ -235,7 +235,8 @@ public class SamlServiceProviderIndexTests extends ESSingleNodeTestCase {
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
indexTemplateRegistry.initialize(); indexTemplateRegistry.initialize();
return List.of(indexTemplateRegistry); return List.of(indexTemplateRegistry);

View file

@ -84,7 +84,8 @@ public class IdentityProviderPlugin extends Plugin implements ActionPlugin {
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
indexTemplateRegistry.initialize(); indexTemplateRegistry.initialize();

View file

@ -8,6 +8,7 @@
package org.elasticsearch.xpack.idp.saml.sp; package org.elasticsearch.xpack.idp.saml.sp;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -31,9 +32,10 @@ public class SamlServiceProviderIndexTemplateRegistry extends IndexTemplateRegis
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
@Override @Override

View file

@ -146,7 +146,8 @@ public class IndexLifecycle extends Plugin implements ActionPlugin, HealthPlugin
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
ilmTemplateRegistry.initialize(); ilmTemplateRegistry.initialize();
ilmHistoryStore.set( ilmHistoryStore.set(

View file

@ -9,6 +9,7 @@ package org.elasticsearch.xpack.ilm.history;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -55,9 +56,10 @@ public class ILMHistoryTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
this.ilmHistoryEnabled = LifecycleSettings.LIFECYCLE_HISTORY_INDEX_ENABLED_SETTING.get(nodeSettings); this.ilmHistoryEnabled = LifecycleSettings.LIFECYCLE_HISTORY_INDEX_ENABLED_SETTING.get(nodeSettings);
} }

View file

@ -25,6 +25,7 @@ import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.LifecycleExecutionState; import org.elasticsearch.cluster.metadata.LifecycleExecutionState;
import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.TriFunction; import org.elasticsearch.common.TriFunction;
import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.ClusterSettings;
@ -80,7 +81,8 @@ public class ILMHistoryStoreTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
NamedXContentRegistry.EMPTY NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
); );
ClusterState state = clusterService.state(); ClusterState state = clusterService.state();
ClusterServiceUtils.setState( ClusterServiceUtils.setState(

View file

@ -89,7 +89,8 @@ public class MigratePlugin extends Plugin implements ActionPlugin, PersistentTas
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
registry.initialize(); registry.initialize();
return List.of(registry); return List.of(registry);

View file

@ -7,6 +7,7 @@
package org.elasticsearch.xpack.migrate; package org.elasticsearch.xpack.migrate;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -31,9 +32,10 @@ public class MigrateTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
@Override @Override

View file

@ -937,7 +937,8 @@ public class MachineLearning extends Plugin
threadPool, threadPool,
client, client,
machineLearningExtension.get().useIlm(), machineLearningExtension.get().useIlm(),
xContentRegistry xContentRegistry,
services.projectResolver()
); );
registry.initialize(); registry.initialize();

View file

@ -8,6 +8,7 @@ package org.elasticsearch.xpack.ml;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -126,9 +127,10 @@ public class MlIndexTemplateRegistry extends IndexTemplateRegistry {
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
boolean useIlm, boolean useIlm,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
this.useIlm = useIlm; this.useIlm = useIlm;
this.composableIndexTemplateConfigs = parseComposableTemplates( this.composableIndexTemplateConfigs = parseComposableTemplates(
anomalyDetectionResultsTemplate(), anomalyDetectionResultsTemplate(),

View file

@ -20,6 +20,7 @@ import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.CollectionUtils; import org.elasticsearch.common.util.CollectionUtils;
@ -91,7 +92,8 @@ public class MlIndexTemplateRegistryTests extends ESTestCase {
threadPool, threadPool,
client, client,
true, true,
xContentRegistry xContentRegistry,
TestProjectResolvers.mustExecuteFirst()
); );
registry.clusterChanged(createClusterChangedEvent(nodes)); registry.clusterChanged(createClusterChangedEvent(nodes));
@ -119,7 +121,8 @@ public class MlIndexTemplateRegistryTests extends ESTestCase {
threadPool, threadPool,
client, client,
false, false,
xContentRegistry xContentRegistry,
TestProjectResolvers.mustExecuteFirst()
); );
registry.clusterChanged(createClusterChangedEvent(nodes)); registry.clusterChanged(createClusterChangedEvent(nodes));

View file

@ -162,7 +162,8 @@ public class Monitoring extends Plugin implements ActionPlugin, ReloadablePlugin
clusterService, clusterService,
threadPool, threadPool,
client, client,
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
templateRegistry.initialize(); templateRegistry.initialize();

View file

@ -11,6 +11,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -243,9 +244,10 @@ public class MonitoringTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
this.clusterService = clusterService; this.clusterService = clusterService;
this.monitoringTemplatesEnabled = MONITORING_TEMPLATES_ENABLED.get(nodeSettings); this.monitoringTemplatesEnabled = MONITORING_TEMPLATES_ENABLED.get(nodeSettings);
} }

View file

@ -24,6 +24,7 @@ import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.TriFunction; import org.elasticsearch.common.TriFunction;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
@ -82,7 +83,14 @@ public class MonitoringTemplateRegistryTests extends ESTestCase {
threadPool = new TestThreadPool(this.getClass().getName()); threadPool = new TestThreadPool(this.getClass().getName());
client = new VerifyingClient(threadPool); client = new VerifyingClient(threadPool);
clusterService = ClusterServiceUtils.createClusterService(threadPool); clusterService = ClusterServiceUtils.createClusterService(threadPool);
registry = new MonitoringTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, NamedXContentRegistry.EMPTY); registry = new MonitoringTemplateRegistry(
Settings.EMPTY,
clusterService,
threadPool,
client,
NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
);
} }
@After @After
@ -115,7 +123,8 @@ public class MonitoringTemplateRegistryTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
NamedXContentRegistry.EMPTY NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
); );
assertThat(disabledRegistry.getLegacyTemplateConfigs(), is(empty())); assertThat(disabledRegistry.getLegacyTemplateConfigs(), is(empty()));
assertThat(disabledRegistry.getComposableTemplateConfigs(), anEmptyMap()); assertThat(disabledRegistry.getComposableTemplateConfigs(), anEmptyMap());
@ -194,7 +203,8 @@ public class MonitoringTemplateRegistryTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
NamedXContentRegistry.EMPTY NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
); );
testRegistry.clusterChanged(event); testRegistry.clusterChanged(event);
} else { } else {

View file

@ -8,6 +8,7 @@
package org.elasticsearch.xpack.oteldata; package org.elasticsearch.xpack.oteldata;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -26,9 +27,10 @@ public class OTelIndexTemplateRegistry extends YamlTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
@Override @Override

View file

@ -48,7 +48,14 @@ public class OTelPlugin extends Plugin implements ActionPlugin {
Settings settings = services.environment().settings(); Settings settings = services.environment().settings();
ClusterService clusterService = services.clusterService(); ClusterService clusterService = services.clusterService();
registry.set( registry.set(
new OTelIndexTemplateRegistry(settings, clusterService, services.threadPool(), services.client(), services.xContentRegistry()) new OTelIndexTemplateRegistry(
settings,
clusterService,
services.threadPool(),
services.client(),
services.xContentRegistry(),
services.projectResolver()
)
); );
if (enabled) { if (enabled) {
OTelIndexTemplateRegistry registryInstance = registry.get(); OTelIndexTemplateRegistry registryInstance = registry.get();

View file

@ -97,7 +97,16 @@ public class ProfilingPlugin extends Plugin implements ActionPlugin {
ThreadPool threadPool = services.threadPool(); ThreadPool threadPool = services.threadPool();
logger.info("Profiling is {}", enabled ? "enabled" : "disabled"); logger.info("Profiling is {}", enabled ? "enabled" : "disabled");
registry.set(new ProfilingIndexTemplateRegistry(settings, clusterService, threadPool, client, services.xContentRegistry())); registry.set(
new ProfilingIndexTemplateRegistry(
settings,
clusterService,
threadPool,
client,
services.xContentRegistry(),
services.projectResolver()
)
);
indexStateResolver.set(new IndexStateResolver(PROFILING_CHECK_OUTDATED_INDICES.get(settings))); indexStateResolver.set(new IndexStateResolver(PROFILING_CHECK_OUTDATED_INDICES.get(settings)));
clusterService.getClusterSettings().addSettingsUpdateConsumer(PROFILING_CHECK_OUTDATED_INDICES, this::updateCheckOutdatedIndices); clusterService.getClusterSettings().addSettingsUpdateConsumer(PROFILING_CHECK_OUTDATED_INDICES, this::updateCheckOutdatedIndices);

View file

@ -13,6 +13,7 @@ import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -79,9 +80,10 @@ public class ProfilingIndexTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
public void setTemplatesEnabled(boolean templatesEnabled) { public void setTemplatesEnabled(boolean templatesEnabled) {

View file

@ -25,6 +25,7 @@ import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ClusterServiceUtils; import org.elasticsearch.test.ClusterServiceUtils;
@ -76,7 +77,14 @@ public class ProfilingIndexTemplateRegistryTests extends ESTestCase {
threadPool = new TestThreadPool(this.getClass().getName()); threadPool = new TestThreadPool(this.getClass().getName());
client = new VerifyingClient(threadPool); client = new VerifyingClient(threadPool);
clusterService = ClusterServiceUtils.createClusterService(threadPool); clusterService = ClusterServiceUtils.createClusterService(threadPool);
registry = new ProfilingIndexTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, NamedXContentRegistry.EMPTY); registry = new ProfilingIndexTemplateRegistry(
Settings.EMPTY,
clusterService,
threadPool,
client,
NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
);
registry.setTemplatesEnabled(true); registry.setTemplatesEnabled(true);
} }

View file

@ -128,7 +128,8 @@ public class SnapshotLifecycle extends Plugin implements ActionPlugin, HealthPlu
clusterService, clusterService,
threadPool, threadPool,
client, client,
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
templateRegistry.initialize(); templateRegistry.initialize();
snapshotHistoryStore.set(new SnapshotHistoryStore(new OriginSettingClient(client, INDEX_LIFECYCLE_ORIGIN), clusterService)); snapshotHistoryStore.set(new SnapshotHistoryStore(new OriginSettingClient(client, INDEX_LIFECYCLE_ORIGIN), clusterService));

View file

@ -10,6 +10,7 @@ package org.elasticsearch.xpack.slm.history;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -62,9 +63,10 @@ public class SnapshotLifecycleTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
slmHistoryEnabled = SLM_HISTORY_INDEX_ENABLED_SETTING.get(nodeSettings); slmHistoryEnabled = SLM_HISTORY_INDEX_ENABLED_SETTING.get(nodeSettings);
} }

View file

@ -23,6 +23,7 @@ import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.TriFunction; import org.elasticsearch.common.TriFunction;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -100,7 +101,14 @@ public class SnapshotLifecycleTemplateRegistryTests extends ESTestCase {
) )
); );
xContentRegistry = new NamedXContentRegistry(entries); xContentRegistry = new NamedXContentRegistry(entries);
registry = new SnapshotLifecycleTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, xContentRegistry); registry = new SnapshotLifecycleTemplateRegistry(
Settings.EMPTY,
clusterService,
threadPool,
client,
xContentRegistry,
TestProjectResolvers.mustExecuteFirst()
);
} }
@After @After
@ -117,7 +125,8 @@ public class SnapshotLifecycleTemplateRegistryTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
xContentRegistry xContentRegistry,
TestProjectResolvers.mustExecuteFirst()
); );
assertThat(disabledRegistry.getComposableTemplateConfigs(), anEmptyMap()); assertThat(disabledRegistry.getComposableTemplateConfigs(), anEmptyMap());
assertThat(disabledRegistry.getLifecyclePolicies(), hasSize(0)); assertThat(disabledRegistry.getLifecyclePolicies(), hasSize(0));

View file

@ -49,3 +49,15 @@ tasks.named("yamlRestCompatTestTransform") { task ->
task.skipTest("stack/10_basic/Test kibana reporting index auto creation", "warning does not exist for compatibility") task.skipTest("stack/10_basic/Test kibana reporting index auto creation", "warning does not exist for compatibility")
task.skipTest("cat.shards/10_basic/Help", "sync_id is removed in 9.0") task.skipTest("cat.shards/10_basic/Help", "sync_id is removed in 9.0")
} }
configurations {
basicRestSpecs {
attributes {
attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE)
}
}
}
artifacts {
basicRestSpecs(new File(projectDir, "src/yamlRestTest/resources/rest-api-spec/test"))
}

View file

@ -12,6 +12,7 @@ import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -91,9 +92,10 @@ public class LegacyStackTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
this.clusterService = clusterService; this.clusterService = clusterService;
this.stackTemplateEnabled = STACK_TEMPLATES_ENABLED.get(nodeSettings); this.stackTemplateEnabled = STACK_TEMPLATES_ENABLED.get(nodeSettings);
} }

View file

@ -33,7 +33,8 @@ public class StackPlugin extends Plugin implements ActionPlugin {
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
legacyStackTemplateRegistry.initialize(); legacyStackTemplateRegistry.initialize();
StackTemplateRegistry stackTemplateRegistry = new StackTemplateRegistry( StackTemplateRegistry stackTemplateRegistry = new StackTemplateRegistry(
@ -41,7 +42,8 @@ public class StackPlugin extends Plugin implements ActionPlugin {
services.clusterService(), services.clusterService(),
services.threadPool(), services.threadPool(),
services.client(), services.client(),
services.xContentRegistry() services.xContentRegistry(),
services.projectResolver()
); );
stackTemplateRegistry.initialize(); stackTemplateRegistry.initialize();
return List.of(legacyStackTemplateRegistry, stackTemplateRegistry); return List.of(legacyStackTemplateRegistry, stackTemplateRegistry);

View file

@ -12,6 +12,7 @@ import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -118,9 +119,10 @@ public class StackTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
this.clusterService = clusterService; this.clusterService = clusterService;
this.stackTemplateEnabled = STACK_TEMPLATES_ENABLED.get(nodeSettings); this.stackTemplateEnabled = STACK_TEMPLATES_ENABLED.get(nodeSettings);
this.componentTemplateConfigs = loadComponentTemplateConfigs(); this.componentTemplateConfigs = loadComponentTemplateConfigs();

View file

@ -10,6 +10,7 @@ package org.elasticsearch.xpack.stack;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComponentTemplate; import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.ingest.PipelineConfiguration; import org.elasticsearch.ingest.PipelineConfiguration;
@ -33,7 +34,14 @@ public class LegacyStackTemplateRegistryTests extends ESTestCase {
threadPool = new TestThreadPool(this.getClass().getName()); threadPool = new TestThreadPool(this.getClass().getName());
Client client = new NoOpClient(threadPool); Client client = new NoOpClient(threadPool);
ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
registry = new LegacyStackTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, NamedXContentRegistry.EMPTY); registry = new LegacyStackTemplateRegistry(
Settings.EMPTY,
clusterService,
threadPool,
client,
NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
);
} }
@After @After

View file

@ -9,6 +9,7 @@ package org.elasticsearch.xpack.stack;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -23,9 +24,10 @@ class StackRegistryWithNonRequiredTemplates extends StackTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
@Override @Override

View file

@ -25,6 +25,7 @@ import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.TriFunction; import org.elasticsearch.common.TriFunction;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -84,7 +85,14 @@ public class StackTemplateRegistryTests extends ESTestCase {
threadPool = new TestThreadPool(this.getClass().getName()); threadPool = new TestThreadPool(this.getClass().getName());
client = new VerifyingClient(threadPool); client = new VerifyingClient(threadPool);
clusterService = ClusterServiceUtils.createClusterService(threadPool); clusterService = ClusterServiceUtils.createClusterService(threadPool);
registry = new StackTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, NamedXContentRegistry.EMPTY); registry = new StackTemplateRegistry(
Settings.EMPTY,
clusterService,
threadPool,
client,
NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
);
} }
@After @After
@ -101,7 +109,8 @@ public class StackTemplateRegistryTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
NamedXContentRegistry.EMPTY NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
); );
assertThat(disabledRegistry.getComposableTemplateConfigs(), anEmptyMap()); assertThat(disabledRegistry.getComposableTemplateConfigs(), anEmptyMap());
} }
@ -113,7 +122,8 @@ public class StackTemplateRegistryTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
NamedXContentRegistry.EMPTY NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
); );
assertThat(disabledRegistry.getComponentTemplateConfigs(), not(anEmptyMap())); assertThat(disabledRegistry.getComponentTemplateConfigs(), not(anEmptyMap()));
assertThat( assertThat(
@ -357,7 +367,8 @@ public class StackTemplateRegistryTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
NamedXContentRegistry.EMPTY NamedXContentRegistry.EMPTY,
TestProjectResolvers.mustExecuteFirst()
); );
DiscoveryNode node = DiscoveryNodeUtils.create("node"); DiscoveryNode node = DiscoveryNodeUtils.create("node");

View file

@ -342,7 +342,8 @@ public class Watcher extends Plugin implements SystemIndexPlugin, ScriptPlugin,
clusterService, clusterService,
threadPool, threadPool,
client, client,
xContentRegistry xContentRegistry,
services.projectResolver()
); );
templateRegistry.initialize(); templateRegistry.initialize();

View file

@ -9,6 +9,7 @@ package org.elasticsearch.xpack.watcher.support;
import org.elasticsearch.client.internal.Client; import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate; import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -37,9 +38,10 @@ public class WatcherIndexTemplateRegistry extends IndexTemplateRegistry {
ClusterService clusterService, ClusterService clusterService,
ThreadPool threadPool, ThreadPool threadPool,
Client client, Client client,
NamedXContentRegistry xContentRegistry NamedXContentRegistry xContentRegistry,
ProjectResolver projectResolver
) { ) {
super(nodeSettings, clusterService, threadPool, client, xContentRegistry); super(nodeSettings, clusterService, threadPool, client, xContentRegistry, projectResolver);
ilmManagementEnabled = Watcher.USE_ILM_INDEX_MANAGEMENT.get(nodeSettings); ilmManagementEnabled = Watcher.USE_ILM_INDEX_MANAGEMENT.get(nodeSettings);
} }

View file

@ -24,6 +24,8 @@ import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.DiscoveryNodeUtils;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.project.ProjectResolver;
import org.elasticsearch.cluster.project.TestProjectResolvers;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.common.util.concurrent.EsExecutors;
@ -80,6 +82,7 @@ public class WatcherIndexTemplateRegistryTests extends ESTestCase {
private ClusterService clusterService; private ClusterService clusterService;
private ThreadPool threadPool; private ThreadPool threadPool;
private Client client; private Client client;
private ProjectResolver projectResolver;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Before @Before
@ -114,7 +117,8 @@ public class WatcherIndexTemplateRegistryTests extends ESTestCase {
) )
); );
xContentRegistry = new NamedXContentRegistry(entries); xContentRegistry = new NamedXContentRegistry(entries);
registry = new WatcherIndexTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, xContentRegistry); projectResolver = TestProjectResolvers.mustExecuteFirst();
registry = new WatcherIndexTemplateRegistry(Settings.EMPTY, clusterService, threadPool, client, xContentRegistry, projectResolver);
} }
public void testThatNonExistingTemplatesAreAddedImmediately() { public void testThatNonExistingTemplatesAreAddedImmediately() {
@ -152,7 +156,8 @@ public class WatcherIndexTemplateRegistryTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
xContentRegistry xContentRegistry,
projectResolver
); );
ClusterChangedEvent event = createClusterChangedEvent(Settings.EMPTY, Collections.emptyMap(), Collections.emptyMap(), nodes); ClusterChangedEvent event = createClusterChangedEvent(Settings.EMPTY, Collections.emptyMap(), Collections.emptyMap(), nodes);
registry.clusterChanged(event); registry.clusterChanged(event);
@ -204,7 +209,8 @@ public class WatcherIndexTemplateRegistryTests extends ESTestCase {
clusterService, clusterService,
threadPool, threadPool,
client, client,
xContentRegistry xContentRegistry,
projectResolver
); );
ClusterChangedEvent event = createClusterChangedEvent(Settings.EMPTY, Collections.emptyMap(), Collections.emptyMap(), nodes); ClusterChangedEvent event = createClusterChangedEvent(Settings.EMPTY, Collections.emptyMap(), Collections.emptyMap(), nodes);
registry.clusterChanged(event); registry.clusterChanged(event);

View file

@ -10,6 +10,7 @@ dependencies {
testImplementation(testArtifact(project(":x-pack:plugin:security:qa:service-account"), "javaRestTest")) testImplementation(testArtifact(project(":x-pack:plugin:security:qa:service-account"), "javaRestTest"))
restXpackTestConfig project(path: ':x-pack:plugin:ilm:qa:rest', configuration: "basicRestSpecs") restXpackTestConfig project(path: ':x-pack:plugin:ilm:qa:rest', configuration: "basicRestSpecs")
restXpackTestConfig project(path: ':x-pack:plugin:downsample:qa:rest', configuration: "basicRestSpecs") restXpackTestConfig project(path: ':x-pack:plugin:downsample:qa:rest', configuration: "basicRestSpecs")
restXpackTestConfig project(path: ':x-pack:plugin:stack', configuration: "basicRestSpecs")
} }
// let the yamlRestTests see the classpath of test // let the yamlRestTests see the classpath of test