Skip to content

Commit 17d8ca4

Browse files
committed
Allow REST tests to run in MP mode
1 parent ac0972b commit 17d8ca4

File tree

2 files changed

+72
-103
lines changed

2 files changed

+72
-103
lines changed

test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java

Lines changed: 70 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.elasticsearch.common.settings.SecureString;
5656
import org.elasticsearch.common.settings.Settings;
5757
import org.elasticsearch.common.ssl.PemUtils;
58+
import org.elasticsearch.common.util.CollectionUtils;
5859
import org.elasticsearch.common.util.concurrent.ThreadContext;
5960
import org.elasticsearch.common.util.set.Sets;
6061
import org.elasticsearch.common.xcontent.XContentHelper;
@@ -92,6 +93,7 @@
9293
import org.junit.After;
9394
import org.junit.AfterClass;
9495
import org.junit.Before;
96+
import org.junit.BeforeClass;
9597

9698
import java.io.BufferedReader;
9799
import java.io.IOException;
@@ -118,6 +120,7 @@
118120
import java.util.HashMap;
119121
import java.util.HashSet;
120122
import java.util.List;
123+
import java.util.Locale;
121124
import java.util.Map;
122125
import java.util.Objects;
123126
import java.util.Optional;
@@ -266,6 +269,9 @@ public static boolean hasXPack() {
266269
private static RestClient cleanupClient;
267270

268271
private static boolean multiProjectEnabled;
272+
private static String activeProject;
273+
private static Set<String> extraProjects;
274+
private static boolean projectsConfigured = false;
269275

270276
public enum ProductFeature {
271277
XPACK,
@@ -357,6 +363,15 @@ protected static boolean testFeatureServiceInitialized() {
357363
return testFeatureService != ALL_FEATURES;
358364
}
359365

366+
@BeforeClass
367+
public static void initializeProjectIds() {
368+
// The active project-id is slightly longer, and has a fixed prefix so that it's easier to pick in error messages etc.
369+
activeProject = "active00" + randomAlphaOfLength(8).toLowerCase(Locale.ROOT);
370+
extraProjects = randomSet(1, 3, () -> randomAlphaOfLength(12).toLowerCase(Locale.ROOT));
371+
// TODO do this in a different way
372+
multiProjectEnabled = Objects.equals(System.getProperty("test.multi_project.enabled"), "true");
373+
}
374+
360375
@Before
361376
public void initClient() throws IOException {
362377
if (client == null) {
@@ -367,17 +382,17 @@ public void initClient() throws IOException {
367382
assert testFeatureServiceInitialized() == false;
368383
clusterHosts = parseClusterHosts(getTestRestCluster());
369384
logger.info("initializing REST clients against {}", clusterHosts);
370-
var clientSettings = restClientSettings();
385+
var clientSettings = addProjectIdToSettings(restClientSettings());
371386
var adminSettings = restAdminSettings();
387+
var cleanupSettings = cleanupClientSettings();
372388
var hosts = clusterHosts.toArray(new HttpHost[0]);
373389
client = buildClient(clientSettings, hosts);
374390
adminClient = clientSettings.equals(adminSettings) ? client : buildClient(adminSettings, hosts);
375-
cleanupClient = getCleanupClient();
391+
cleanupClient = adminSettings.equals(cleanupSettings) ? adminClient : buildClient(cleanupSettings, hosts);
376392

377393
availableFeatures = EnumSet.of(ProductFeature.LEGACY_TEMPLATES);
378394
Set<String> versions = new HashSet<>();
379395
boolean serverless = false;
380-
String multiProjectPluginVariant = null;
381396

382397
for (Map<?, ?> nodeInfo : getNodesInfo(adminClient).values()) {
383398
var nodeVersion = nodeInfo.get("version").toString();
@@ -407,11 +422,6 @@ public void initClient() throws IOException {
407422
if (moduleName.startsWith("serverless-")) {
408423
serverless = true;
409424
}
410-
if (moduleName.contains("test-multi-project")) {
411-
multiProjectPluginVariant = "test";
412-
} else if (moduleName.contains("serverless-multi-project")) {
413-
multiProjectPluginVariant = "serverless";
414-
}
415425
}
416426
if (serverless) {
417427
availableFeatures.removeAll(
@@ -432,22 +442,11 @@ public void initClient() throws IOException {
432442
.flatMap(Optional::stream)
433443
.collect(Collectors.toSet());
434444
assert semanticNodeVersions.isEmpty() == false || serverless;
435-
436-
if (multiProjectPluginVariant != null) {
437-
final Request settingRequest = new Request(
438-
"GET",
439-
"/_cluster/settings?include_defaults&filter_path=*." + multiProjectPluginVariant + ".multi_project.enabled"
440-
);
441-
settingRequest.setOptions(RequestOptions.DEFAULT.toBuilder().setWarningsHandler(WarningsHandler.PERMISSIVE));
442-
final var response = entityAsMap(adminClient.performRequest(settingRequest));
443-
multiProjectEnabled = Boolean.parseBoolean(
444-
ObjectPath.evaluate(response, "defaults." + multiProjectPluginVariant + ".multi_project.enabled")
445-
);
446-
}
447-
448445
testFeatureService = createTestFeatureService(getClusterStateFeatures(adminClient), semanticNodeVersions);
449446
}
450447

448+
configureProjects();
449+
451450
assert testFeatureServiceInitialized();
452451
assert client != null;
453452
assert adminClient != null;
@@ -456,6 +455,40 @@ public void initClient() throws IOException {
456455
assert nodesVersions != null;
457456
}
458457

458+
private void configureProjects() throws IOException {
459+
if (projectsConfigured || multiProjectEnabled == false) {
460+
return;
461+
}
462+
projectsConfigured = true;
463+
createProject(activeProject);
464+
for (var project : extraProjects) {
465+
createProject(project);
466+
}
467+
468+
// The admin client does not set a project id, and can see all projects
469+
assertProjectIds(
470+
adminClient(),
471+
CollectionUtils.concatLists(List.of(Metadata.DEFAULT_PROJECT_ID.id(), activeProject), extraProjects)
472+
);
473+
// The test client can only see the project it targets
474+
assertProjectIds(client(), List.of(activeProject));
475+
}
476+
477+
@After
478+
public final void assertEmptyProjects() throws Exception {
479+
if (multiProjectEnabled == false) {
480+
return;
481+
}
482+
assertEmptyProject(Metadata.DEFAULT_PROJECT_ID.id());
483+
for (var project : extraProjects) {
484+
assertEmptyProject(project);
485+
}
486+
}
487+
488+
public static String activeProject() {
489+
return activeProject;
490+
}
491+
459492
protected final TestFeatureService createTestFeatureService(
460493
Map<String, Set<String>> clusterStateFeatures,
461494
Set<Version> semanticNodeVersions
@@ -1604,10 +1637,6 @@ protected Settings restClientSettings() {
16041637
String token = basicAuthHeaderValue(username, new SecureString(password.toCharArray()));
16051638
builder.put(ThreadContext.PREFIX + ".Authorization", token);
16061639
}
1607-
if (System.getProperty("tests.rest.project.id") != null) {
1608-
final var projectId = System.getProperty("tests.rest.project.id");
1609-
builder.put(ThreadContext.PREFIX + ".X-Elastic-Project-Id", projectId);
1610-
}
16111640
return builder.build();
16121641
}
16131642

@@ -1621,9 +1650,21 @@ protected Settings restAdminSettings() {
16211650
/**
16221651
* Returns the REST client used for cleaning up the cluster.
16231652
*/
1624-
protected RestClient getCleanupClient() {
1625-
assert adminClient != null;
1626-
return adminClient;
1653+
protected Settings cleanupClientSettings() {
1654+
if (multiProjectEnabled == false) {
1655+
return restAdminSettings();
1656+
}
1657+
return addProjectIdToSettings(restAdminSettings());
1658+
}
1659+
1660+
private Settings addProjectIdToSettings(Settings settings) {
1661+
if (multiProjectEnabled == false) {
1662+
return settings;
1663+
}
1664+
return Settings.builder()
1665+
.put(settings)
1666+
.put(ThreadContext.PREFIX + "." + Task.X_ELASTIC_PROJECT_ID_HTTP_HEADER, activeProject)
1667+
.build();
16271668
}
16281669

16291670
/**
@@ -2716,10 +2757,9 @@ protected static void assertResultMap(
27162757

27172758
protected void createProject(String project) throws IOException {
27182759
assert multiProjectEnabled;
2719-
RestClient client = adminClient();
27202760
final Request request = new Request("PUT", "/_project/" + project);
27212761
try {
2722-
final Response response = client.performRequest(request);
2762+
final Response response = adminClient().performRequest(request);
27232763
logger.info("Created project {} : {}", project, response.getStatusLine());
27242764
} catch (ResponseException e) {
27252765
logger.error("Failed to create project: {}", project);
@@ -2790,16 +2830,12 @@ protected void assertEmptyProject(String projectId) throws IOException {
27902830
if (indexTemplates != null) {
27912831
var templateNames = indexTemplates.keySet().stream().filter(name -> isXPackTemplate(name) == false).toList();
27922832
assertThat("Project [" + projectId + "] should not have index templates", templateNames, empty());
2793-
} else if (projectId.equals(Metadata.DEFAULT_PROJECT_ID.id())) {
2794-
fail("Expected default project to have standard templates, but was null");
27952833
}
27962834

27972835
final Map<String, Object> componentTemplates = state.evaluate("metadata.component_template.component_template");
27982836
if (componentTemplates != null) {
27992837
var templateNames = componentTemplates.keySet().stream().filter(name -> isXPackTemplate(name) == false).toList();
28002838
assertThat("Project [" + projectId + "] should not have component templates", templateNames, empty());
2801-
} else if (projectId.equals(Metadata.DEFAULT_PROJECT_ID.id())) {
2802-
fail("Expected default project to have standard component templates, but was null");
28032839
}
28042840

28052841
final List<Map<String, ?>> pipelines = state.evaluate("metadata.ingest.pipeline");
@@ -2809,8 +2845,6 @@ protected void assertEmptyProject(String projectId) throws IOException {
28092845
.filter(id -> isXPackIngestPipeline(id) == false)
28102846
.toList();
28112847
assertThat("Project [" + projectId + "] should not have ingest pipelines", pipelineNames, empty());
2812-
} else if (projectId.equals(Metadata.DEFAULT_PROJECT_ID.id())) {
2813-
fail("Expected default project to have standard ingest pipelines, but was null");
28142848
}
28152849

28162850
if (has(ProductFeature.ILM)) {
@@ -2819,8 +2853,6 @@ protected void assertEmptyProject(String projectId) throws IOException {
28192853
var policyNames = new HashSet<>(ilmPolicies.keySet());
28202854
policyNames.removeAll(preserveILMPolicyIds());
28212855
assertThat("Project [" + projectId + "] should not have ILM Policies", policyNames, empty());
2822-
} else if (projectId.equals(Metadata.DEFAULT_PROJECT_ID.id())) {
2823-
fail("Expected default project to have standard ILM policies, but was null");
28242856
}
28252857
}
28262858
}

x-pack/qa/multi-project/yaml-test-framework/src/main/java/org/elasticsearch/multiproject/test/MultipleProjectsClientYamlSuiteTestCase.java

Lines changed: 2 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,13 @@
77

88
package org.elasticsearch.multiproject.test;
99

10-
import org.elasticsearch.client.RestClient;
11-
import org.elasticsearch.cluster.metadata.Metadata;
1210
import org.elasticsearch.common.settings.SecureString;
1311
import org.elasticsearch.common.settings.Settings;
14-
import org.elasticsearch.common.util.CollectionUtils;
1512
import org.elasticsearch.common.util.concurrent.ThreadContext;
16-
import org.elasticsearch.tasks.Task;
1713
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
1814
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
19-
import org.junit.After;
20-
import org.junit.Before;
21-
import org.junit.BeforeClass;
2215

23-
import java.util.List;
24-
import java.util.Locale;
2516
import java.util.Objects;
26-
import java.util.Set;
2717

2818
/**
2919
* Base class for running YAML Rest tests against a cluster with multiple projects
@@ -39,73 +29,20 @@ public abstract class MultipleProjectsClientYamlSuiteTestCase extends ESClientYa
3929
*/
4030
protected static final String PASS = Objects.requireNonNull(System.getProperty("tests.rest.cluster.password", "test-password"));
4131

42-
private static String activeProject;
43-
private static Set<String> extraProjects;
44-
private static boolean projectsConfigured = false;
45-
4632
public MultipleProjectsClientYamlSuiteTestCase(ClientYamlTestCandidate testCandidate) {
4733
super(testCandidate);
4834
}
4935

50-
@BeforeClass
51-
public static void initializeProjectIds() {
52-
// The active project-id is slightly longer, and has a fixed suffix so that it's easier to pick in error messages etc.
53-
activeProject = randomAlphaOfLength(8).toLowerCase(Locale.ROOT) + "00active";
54-
extraProjects = randomSet(1, 3, () -> randomAlphaOfLength(12).toLowerCase(Locale.ROOT));
55-
}
56-
57-
@Override
58-
protected RestClient getCleanupClient() {
59-
return client();
60-
}
61-
62-
@Before
63-
public void configureProjects() throws Exception {
64-
if (projectsConfigured) {
65-
return;
66-
}
67-
projectsConfigured = true;
68-
initClient();
69-
createProject(activeProject);
70-
for (var project : extraProjects) {
71-
createProject(project);
72-
}
73-
74-
// The admin client does not set a project id, and can see all projects
75-
assertProjectIds(
76-
adminClient(),
77-
CollectionUtils.concatLists(List.of(Metadata.DEFAULT_PROJECT_ID.id(), activeProject), extraProjects)
78-
);
79-
// The test client can only see the project it targets
80-
assertProjectIds(client(), List.of(activeProject));
81-
}
82-
83-
@After
84-
public final void assertEmptyProjects() throws Exception {
85-
assertEmptyProject(Metadata.DEFAULT_PROJECT_ID.id());
86-
for (var project : extraProjects) {
87-
assertEmptyProject(project);
88-
}
89-
}
90-
9136
@Override
9237
protected Settings restClientSettings() {
93-
return clientSettings(true);
94-
}
95-
96-
@Override
97-
protected Settings restAdminSettings() {
98-
return clientSettings(false);
38+
return clientSettings();
9939
}
10040

101-
private Settings clientSettings(boolean projectScoped) {
41+
private Settings clientSettings() {
10242
String token = basicAuthHeaderValue(USER, new SecureString(PASS.toCharArray()));
10343
final Settings.Builder builder = Settings.builder()
10444
.put(super.restClientSettings())
10545
.put(ThreadContext.PREFIX + ".Authorization", token);
106-
if (projectScoped) {
107-
builder.put(ThreadContext.PREFIX + "." + Task.X_ELASTIC_PROJECT_ID_HTTP_HEADER, activeProject);
108-
}
10946
return builder.build();
11047
}
11148
}

0 commit comments

Comments
 (0)