浏览代码

Rework minio test fixture and its usages (#102707)

* Update minio fixture and usages to rely on new test cluster framework and testcontainer
* Cache test fixture resources during packer caching

Add logic that ensures we resolve docker images resolved from docker registry as part of our packer
cache setup.
Rene Groeschke 1 年之前
父节点
当前提交
26905047fb
共有 18 个文件被更改,包括 290 次插入130 次删除
  1. 6 0
      build-tools-internal/build.gradle
  2. 0 2
      build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java
  3. 115 0
      build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/packer/CacheCacheableTestFixtures.java
  4. 45 0
      build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/packer/CacheTestFixtureResourcesPlugin.java
  5. 4 0
      build-tools-internal/version.properties
  6. 1 0
      gradle/build.versions.toml
  7. 5 0
      gradle/verification-metadata.xml
  8. 0 2
      test/fixtures/geoip-fixture/build.gradle
  9. 0 9
      test/fixtures/minio-fixture/Dockerfile
  10. 6 2
      test/fixtures/minio-fixture/build.gradle
  11. 0 35
      test/fixtures/minio-fixture/docker-compose.yml
  12. 13 0
      test/fixtures/minio-fixture/src/main/java/org/elasticsearch/test/fixtures/CacheableTestFixture.java
  13. 13 2
      test/fixtures/minio-fixture/src/main/java/org/elasticsearch/test/fixtures/minio/MinioTestContainer.java
  14. 8 33
      x-pack/plugin/searchable-snapshots/qa/minio/build.gradle
  15. 36 9
      x-pack/plugin/searchable-snapshots/qa/minio/src/javaRestTest/java/org/elasticsearch/xpack/searchablesnapshots/minio/MinioSearchableSnapshotsIT.java
  16. 1 1
      x-pack/plugin/snapshot-repo-test-kit/qa/hdfs/build.gradle
  17. 4 26
      x-pack/plugin/snapshot-repo-test-kit/qa/minio/build.gradle
  18. 33 9
      x-pack/plugin/snapshot-repo-test-kit/qa/minio/src/javaRestTest/java/org/elasticsearch/repositories/blobstore/testkit/MinioSnapshotRepoTestKitIT.java

+ 6 - 0
build-tools-internal/build.gradle

@@ -195,6 +195,10 @@ gradlePlugin {
       id = 'elasticsearch.legacy-yaml-rest-test'
       implementationClass = 'org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin'
     }
+    cacheTestFixtures {
+        id = 'elasticsearch.cache-test-fixtures'
+        implementationClass = 'org.elasticsearch.gradle.internal.packer.CacheTestFixtureResourcesPlugin'
+    }
     yamlRestTest {
       id = 'elasticsearch.internal-yaml-rest-test'
       implementationClass = 'org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin'
@@ -288,6 +292,8 @@ dependencies {
   api buildLibs.httpcore
 
   compileOnly buildLibs.checkstyle
+  compileOnly buildLibs.reflections
+
   runtimeOnly "org.elasticsearch.gradle:reaper:$version"
   testImplementation buildLibs.checkstyle
   testImplementation buildLibs.wiremock

+ 0 - 2
build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RestrictedBuildApiService.java

@@ -139,7 +139,6 @@ public abstract class RestrictedBuildApiService implements BuildService<Restrict
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ml:qa:native-multi-node-tests");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:ml:qa:single-node-tests");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:searchable-snapshots:qa:hdfs");
-        map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:searchable-snapshots:qa:minio");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:searchable-snapshots:qa:rest");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:searchable-snapshots:qa:url");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:security:qa:tls-basic");
@@ -150,7 +149,6 @@ public abstract class RestrictedBuildApiService implements BuildService<Restrict
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-based-recoveries:qa:fs");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-based-recoveries:qa:license-enforcing");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-repo-test-kit:qa:hdfs");
-        map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-repo-test-kit:qa:minio");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:snapshot-repo-test-kit:qa:rest");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:jdbc:multi-node");
         map.put(LegacyRestTestBasePlugin.class, ":x-pack:plugin:sql:qa:jdbc:no-sql");

+ 115 - 0
build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/packer/CacheCacheableTestFixtures.java

@@ -0,0 +1,115 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal.packer;
+
+import org.gradle.api.DefaultTask;
+import org.gradle.api.InvalidUserDataException;
+import org.gradle.api.file.ConfigurableFileCollection;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.tasks.CompileClasspath;
+import org.gradle.api.tasks.TaskAction;
+import org.gradle.workers.WorkAction;
+import org.gradle.workers.WorkParameters;
+import org.gradle.workers.WorkQueue;
+import org.gradle.workers.WorkerExecutor;
+import org.reflections.Reflections;
+import org.reflections.scanners.SubTypesScanner;
+import org.reflections.util.ClasspathHelper;
+import org.reflections.util.ConfigurationBuilder;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+public abstract class CacheCacheableTestFixtures extends DefaultTask {
+
+    @CompileClasspath
+    public abstract ConfigurableFileCollection getClasspath();
+
+    @Inject
+    public abstract WorkerExecutor getWorkerExecutor();
+
+    /**
+     * Executes the forbidden apis task.
+     */
+    @TaskAction
+    public void checkForbidden() {
+        WorkQueue workQueue = getWorkerExecutor().classLoaderIsolation(spec -> spec.getClasspath().from(getClasspath()));
+        workQueue.submit(CacheTestFixtureWorkAction.class, params -> params.getClasspath().setFrom(getClasspath()));
+    }
+
+    interface Parameters extends WorkParameters {
+        ConfigurableFileCollection getClasspath();
+    }
+
+    abstract static class CacheTestFixtureWorkAction implements WorkAction<Parameters> {
+
+        @Inject
+        @SuppressWarnings("checkstyle:RedundantModifier")
+        public CacheTestFixtureWorkAction() {}
+
+        @Override
+        public void execute() {
+            final URLClassLoader urlLoader = createClassLoader(getParameters().getClasspath());
+            try {
+                Reflections reflections = new Reflections(
+                    new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage("org.elasticsearch.test.fixtures"))
+                        .setScanners(new SubTypesScanner())
+                );
+
+                Class<?> ifClass = Class.forName("org.elasticsearch.test.fixtures.CacheableTestFixture");
+                Set<Class<?>> classes = (Set<Class<?>>) reflections.getSubTypesOf(ifClass);
+
+                for (Class<?> cacheableTestFixtureClazz : classes) {
+                    Object o = cacheableTestFixtureClazz.getDeclaredConstructor().newInstance();
+                    Method cacheMethod = cacheableTestFixtureClazz.getMethod("cache");
+                    cacheMethod.invoke(o);
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            } finally {
+                // Close the classloader to free resources:
+                try {
+                    if (urlLoader != null) urlLoader.close();
+                } catch (IOException ioe) {
+                    // getLogger().warn("Cannot close classloader: ".concat(ioe.toString()));
+                }
+            }
+        }
+
+        private URLClassLoader createClassLoader(FileCollection classpath) {
+            if (classpath == null) {
+                throw new InvalidUserDataException("Missing 'classesDirs' or 'classpath' property.");
+            }
+
+            final Set<File> cpElements = new LinkedHashSet<>();
+            cpElements.addAll(classpath.getFiles());
+            final URL[] urls = new URL[cpElements.size()];
+            try {
+                int i = 0;
+                for (final File cpElement : cpElements) {
+                    urls[i++] = cpElement.toURI().toURL();
+                }
+                assert i == urls.length;
+            } catch (MalformedURLException mfue) {
+                throw new InvalidUserDataException("Failed to build classpath URLs.", mfue);
+            }
+
+            return URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());
+        }
+
+    }
+}

+ 45 - 0
build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/packer/CacheTestFixtureResourcesPlugin.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal.packer;
+
+import org.elasticsearch.gradle.VersionProperties;
+import org.elasticsearch.gradle.internal.ResolveAllDependencies;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.dsl.DependencyHandler;
+import org.gradle.api.plugins.JavaPlugin;
+import org.gradle.api.plugins.JavaPluginExtension;
+
+public class CacheTestFixtureResourcesPlugin implements Plugin<Project> {
+
+    public static final String CACHE_TEST_FIXTURES = "cacheTestFixtures";
+
+    @Override
+    public void apply(Project project) {
+
+        var cacheTestFixturesConfiguration = project.getConfigurations().create(CACHE_TEST_FIXTURES);
+        cacheTestFixturesConfiguration.defaultDependencies(deps -> {
+            DependencyHandler dependencyHandler = project.getDependencies();
+            deps.add(dependencyHandler.create("org.reflections:reflections:" + VersionProperties.getVersions().get("reflections")));
+            deps.add(dependencyHandler.create("org.javassist:javassist:" + VersionProperties.getVersions().get("javassist")));
+        });
+        project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
+            var cacheTestFixtures = project.getTasks().register(CACHE_TEST_FIXTURES, CacheCacheableTestFixtures.class, (t) -> {
+                var testSourceSet = project.getExtensions()
+                    .getByType(JavaPluginExtension.class)
+                    .getSourceSets()
+                    .getByName(JavaPlugin.TEST_TASK_NAME);
+                t.getClasspath().from(cacheTestFixturesConfiguration);
+                t.getClasspath().from(testSourceSet.getRuntimeClasspath());
+            });
+            project.getTasks().withType(ResolveAllDependencies.class).configureEach(r -> r.dependsOn(cacheTestFixtures));
+        });
+
+    }
+}

+ 4 - 0
build-tools-internal/version.properties

@@ -47,6 +47,10 @@ dockerJava        = 3.3.4
 ductTape          = 1.0.8
 commonsCompress   = 1.24.0
 
+# packer caching build logic
+reflections       = 0.9.12
+javassist         = 3.28.0-GA
+
 # benchmark dependencies
 jmh               = 1.26
 

+ 1 - 0
gradle/build.versions.toml

@@ -37,6 +37,7 @@ junit5-vintage = { group = "org.junit.vintage", name="junit-vintage-engine", ver
 maven-model = "org.apache.maven:maven-model:3.6.2"
 mockito-core = "org.mockito:mockito-core:1.9.5"
 nebula-info = "com.netflix.nebula:gradle-info-plugin:11.3.3"
+reflections = "org.reflections:reflections:0.9.12"
 shadow-plugin = "com.github.johnrengelman:shadow:8.1.1"
 spock-core = { group = "org.spockframework", name="spock-core", version.ref="spock" }
 spock-junit4 = { group = "org.spockframework", name="spock-junit4", version.ref="spock" }

+ 5 - 0
gradle/verification-metadata.xml

@@ -4092,6 +4092,11 @@
             <sha256 value="938a2d08fe54050d7610b944d8ddc3a09355710d9e6be0aac838dbc04e9a2825" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="org.reflections" name="reflections" version="0.9.12">
+         <artifact name="reflections-0.9.12.jar">
+            <sha256 value="d168f58d32f2ae7ac5a8d5d9092adeee526c604b41125dcb45eea877960a99cf" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="org.rnorth.duct-tape" name="duct-tape" version="1.0.8">
          <artifact name="duct-tape-1.0.8.jar">
             <sha256 value="31cef12ddec979d1f86d7cf708c41a17da523d05c685fd6642e9d0b2addb7240" origin="Generated by Gradle"/>

+ 0 - 2
test/fixtures/geoip-fixture/build.gradle

@@ -18,5 +18,3 @@ dependencies {
     exclude module: 'hamcrest-core'
   }
 }
-
-tasks.named("test") { enabled = false }

+ 0 - 9
test/fixtures/minio-fixture/Dockerfile

@@ -1,9 +0,0 @@
-FROM minio/minio:RELEASE.2021-03-01T04-20-55Z
-
-ARG bucket
-ARG accessKey
-ARG secretKey
-
-RUN mkdir -p /minio/data/${bucket}
-ENV MINIO_ACCESS_KEY=${accessKey}
-ENV MINIO_SECRET_KEY=${secretKey}

+ 6 - 2
test/fixtures/minio-fixture/build.gradle

@@ -5,9 +5,9 @@
  * in compliance with, at your election, the Elastic License 2.0 or the Server
  * Side Public License, v 1.
  */
-apply plugin: 'elasticsearch.test.fixtures'
 apply plugin: 'java'
 apply plugin: 'elasticsearch.java'
+apply plugin: 'elasticsearch.cache-test-fixtures'
 
 description = 'Fixture for MinIO Storage service'
 
@@ -23,10 +23,14 @@ dependencies {
   implementation "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
   implementation "org.slf4j:slf4j-api:${versions.slf4j}"
   implementation "com.github.docker-java:docker-java-api:${versions.dockerJava}"
+
   runtimeOnly "com.github.docker-java:docker-java-transport-zerodep:${versions.dockerJava}"
   runtimeOnly "com.github.docker-java:docker-java-transport:${versions.dockerJava}"
   runtimeOnly "com.github.docker-java:docker-java-core:${versions.dockerJava}"
   runtimeOnly "org.apache.commons:commons-compress:${versions.commonsCompress}"
   runtimeOnly "org.rnorth.duct-tape:duct-tape:${versions.ductTape}"
-  runtimeOnly "org.rnorth.duct-tape:duct-tape:${versions.ductTape}"
+
+  // ensure we have proper logging during when used in tests
+  runtimeOnly "org.slf4j:slf4j-simple:${versions.slf4j}"
+  runtimeOnly "org.hamcrest:hamcrest:${versions.hamcrest}"
 }

+ 0 - 35
test/fixtures/minio-fixture/docker-compose.yml

@@ -1,35 +0,0 @@
-version: '3'
-services:
-  minio-fixture:
-    build:
-      context: .
-      args:
-        bucket: "bucket"
-        accessKey: "s3_test_access_key"
-        secretKey: "s3_test_secret_key"
-      dockerfile: Dockerfile
-    ports:
-      - "9000"
-    command: ["server", "/minio/data"]
-  minio-fixture-other:
-    build:
-      context: .
-      args:
-        bucket: "bucket"
-        accessKey: "s3_test_access_key"
-        secretKey: "s3_test_secret_key"
-      dockerfile: Dockerfile
-    ports:
-      - "9000"
-    command: ["server", "/minio/data"]
-  minio-fixture-repository-test-kit:
-    build:
-      context: .
-      args:
-        bucket: "bucket"
-        accessKey: "s3_test_access_key"
-        secretKey: "s3_test_secret_key"
-      dockerfile: Dockerfile
-    ports:
-      - "9000"
-    command: ["server", "/minio/data"]

+ 13 - 0
test/fixtures/minio-fixture/src/main/java/org/elasticsearch/test/fixtures/CacheableTestFixture.java

@@ -0,0 +1,13 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.test.fixtures;
+
+public interface CacheableTestFixture {
+    void cache();
+}

+ 13 - 2
test/fixtures/minio-fixture/src/main/java/org/elasticsearch/test/fixtures/minio/MinioTestContainer.java

@@ -8,13 +8,15 @@
 
 package org.elasticsearch.test.fixtures.minio;
 
+import org.elasticsearch.test.fixtures.CacheableTestFixture;
 import org.elasticsearch.test.fixtures.testcontainers.DockerEnvironmentAwareTestContainer;
 import org.junit.rules.TestRule;
 import org.testcontainers.images.builder.ImageFromDockerfile;
 
-public final class MinioTestContainer extends DockerEnvironmentAwareTestContainer implements TestRule {
+public final class MinioTestContainer extends DockerEnvironmentAwareTestContainer implements TestRule, CacheableTestFixture {
 
     private static final int servicePort = 9000;
+    public static final String DOCKER_BASE_IMAGE = "minio/minio:RELEASE.2021-03-01T04-20-55Z";
     private final boolean enabled;
 
     public MinioTestContainer() {
@@ -24,7 +26,7 @@ public final class MinioTestContainer extends DockerEnvironmentAwareTestContaine
     public MinioTestContainer(boolean enabled) {
         super(
             new ImageFromDockerfile().withDockerfileFromBuilder(
-                builder -> builder.from("minio/minio:RELEASE.2021-03-01T04-20-55Z")
+                builder -> builder.from(DOCKER_BASE_IMAGE)
                     .env("MINIO_ACCESS_KEY", "s3_test_access_key")
                     .env("MINIO_SECRET_KEY", "s3_test_secret_key")
                     .run("mkdir -p /minio/data/bucket")
@@ -48,4 +50,13 @@ public final class MinioTestContainer extends DockerEnvironmentAwareTestContaine
     public String getAddress() {
         return "http://127.0.0.1:" + getMappedPort(servicePort);
     }
+
+    public void cache() {
+        try {
+            start();
+            stop();
+        } catch (RuntimeException e) {
+            logger().warn("Error while caching container images.", e);
+        }
+    }
 }

+ 8 - 33
x-pack/plugin/searchable-snapshots/qa/minio/build.gradle

@@ -1,13 +1,17 @@
 import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
 
-apply plugin: 'elasticsearch.legacy-java-rest-test'
-apply plugin: 'elasticsearch.test.fixtures'
+apply plugin: 'elasticsearch.internal-java-rest-test'
 apply plugin: 'elasticsearch.rest-resources'
 
-final Project fixture = project(':test:fixtures:minio-fixture')
-
 dependencies {
   javaRestTestImplementation(testArtifact(project(xpackModule('searchable-snapshots'))))
+  javaRestTestImplementation project(':test:test-clusters')
+  javaRestTestImplementation project(":test:framework")
+  javaRestTestImplementation project(':test:fixtures:minio-fixture')
+}
+
+tasks.named('javaRestTest') {
+  usesDefaultDistribution()
 }
 
 restResources {
@@ -15,32 +19,3 @@ restResources {
     include 'indices', 'search', 'bulk', 'snapshot', 'nodes', '_common', 'searchable_snapshots'
   }
 }
-
-testFixtures.useFixture(fixture.path, 'minio-fixture-other')
-def fixtureAddress = {
-  int ephemeralPort =  fixture.postProcessFixture.ext."test.fixtures.minio-fixture-other.tcp.9000"
-  assert ephemeralPort > 0
-  '127.0.0.1:' + ephemeralPort
-}
-
-tasks.named("javaRestTest").configure {
-  systemProperty 'test.minio.bucket', 'bucket'
-  systemProperty 'test.minio.base_path', 'searchable_snapshots_tests'
-}
-
-testClusters.matching { it.name == "javaRestTest" }.configureEach {
-  testDistribution = 'DEFAULT'
-
-  keystore 's3.client.searchable_snapshots.access_key', 's3_test_access_key'
-  keystore 's3.client.searchable_snapshots.secret_key', 's3_test_secret_key'
-  setting 'xpack.license.self_generated.type', 'trial'
-  setting 's3.client.searchable_snapshots.protocol', 'http'
-  setting 's3.client.searchable_snapshots.endpoint', { "${-> fixtureAddress()}" }, IGNORE_VALUE
-
-  setting 'xpack.searchable.snapshot.shared_cache.size', '16MB'
-  setting 'xpack.searchable.snapshot.shared_cache.region_size', '256KB'
-  setting 'xpack.searchable_snapshots.cache_fetch_async_thread_pool.keep_alive', '0ms'
-
-  setting 'xpack.security.enabled', 'false'
-}
-

+ 36 - 9
x-pack/plugin/searchable-snapshots/qa/minio/src/javaRestTest/java/org/elasticsearch/xpack/searchablesnapshots/minio/MinioSearchableSnapshotsIT.java

@@ -6,27 +6,54 @@
  */
 package org.elasticsearch.xpack.searchablesnapshots.minio;
 
+import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
+
 import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.test.cluster.ElasticsearchCluster;
+import org.elasticsearch.test.cluster.local.distribution.DistributionType;
+import org.elasticsearch.test.fixtures.minio.MinioTestContainer;
+import org.elasticsearch.test.fixtures.testcontainers.TestContainersThreadFilter;
 import org.elasticsearch.xpack.searchablesnapshots.AbstractSearchableSnapshotsRestTestCase;
+import org.junit.ClassRule;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
 
-import static org.hamcrest.Matchers.blankOrNullString;
-import static org.hamcrest.Matchers.not;
-
+@ThreadLeakFilters(filters = { TestContainersThreadFilter.class })
 public class MinioSearchableSnapshotsIT extends AbstractSearchableSnapshotsRestTestCase {
 
+    public static final MinioTestContainer minioFixture = new MinioTestContainer();
+
+    public static ElasticsearchCluster cluster = ElasticsearchCluster.local()
+        .distribution(DistributionType.DEFAULT)
+        .keystore("s3.client.searchable_snapshots.access_key", "s3_test_access_key")
+        .keystore("s3.client.searchable_snapshots.secret_key", "s3_test_secret_key")
+        .setting("xpack.license.self_generated.type", "trial")
+        .setting("s3.client.searchable_snapshots.protocol", () -> "http")
+        .setting("s3.client.searchable_snapshots.endpoint", minioFixture::getAddress)
+        .setting("xpack.searchable.snapshot.shared_cache.size", "16MB")
+        .setting("xpack.searchable.snapshot.shared_cache.region_size", "256KB")
+        .setting("xpack.searchable_snapshots.cache_fetch_async_thread_pool.keep_alive", "0ms")
+        .setting("xpack.security.enabled", "false")
+        .setting("xpack.ml.enabled", "false")
+        .build();
+
+    @ClassRule
+    public static TestRule ruleChain = RuleChain.outerRule(minioFixture).around(cluster);
+
     @Override
     protected String writeRepositoryType() {
         return "s3";
     }
 
     @Override
-    protected Settings writeRepositorySettings() {
-        final String bucket = System.getProperty("test.minio.bucket");
-        assertThat(bucket, not(blankOrNullString()));
-
-        final String basePath = System.getProperty("test.minio.base_path");
-        assertThat(basePath, not(blankOrNullString()));
+    protected String getTestRestCluster() {
+        return cluster.getHttpAddresses();
+    }
 
+    @Override
+    protected Settings writeRepositorySettings() {
+        final String bucket = "bucket";
+        final String basePath = "searchable_snapshots_tests";
         return Settings.builder().put("client", "searchable_snapshots").put("bucket", bucket).put("base_path", basePath).build();
     }
 }

+ 1 - 1
x-pack/plugin/snapshot-repo-test-kit/qa/hdfs/build.gradle

@@ -27,7 +27,7 @@ final Project hdfsRepoPluginProject = project(':plugins:repository-hdfs')
 
 dependencies {
   javaRestTestImplementation testArtifact(project(xpackModule('snapshot-repo-test-kit')))
-  javaRestTestImplementation hdfsRepoPluginProject
+  javaRestTestImplementation project(':plugins:repository-hdfs')
 }
 
 restResources {

+ 4 - 26
x-pack/plugin/snapshot-repo-test-kit/qa/minio/build.gradle

@@ -7,14 +7,12 @@
 
 import static org.elasticsearch.gradle.PropertyNormalization.IGNORE_VALUE
 
-apply plugin: 'elasticsearch.legacy-java-rest-test'
-apply plugin: 'elasticsearch.test.fixtures'
+apply plugin: 'elasticsearch.internal-java-rest-test'
 apply plugin: 'elasticsearch.rest-resources'
 
-final Project fixture = project(':test:fixtures:minio-fixture')
-
 dependencies {
   javaRestTestImplementation testArtifact(project(xpackModule('snapshot-repo-test-kit')))
+  javaRestTestImplementation project(':test:fixtures:minio-fixture')
 }
 
 restResources {
@@ -23,26 +21,6 @@ restResources {
   }
 }
 
-testFixtures.useFixture(fixture.path, 'minio-fixture-repository-test-kit')
-def fixtureAddress = {
-  int ephemeralPort =  fixture.postProcessFixture.ext."test.fixtures.minio-fixture-repository-test-kit.tcp.9000"
-  assert ephemeralPort > 0
-  '127.0.0.1:' + ephemeralPort
-}
-
-tasks.named("javaRestTest").configure {
-  systemProperty 'test.minio.bucket', 'bucket'
-  systemProperty 'test.minio.base_path', 'repository_test_kit_tests'
-}
-
-testClusters.matching { it.name == "javaRestTest" }.configureEach {
-  testDistribution = 'DEFAULT'
-
-  keystore 's3.client.repository_test_kit.access_key', 's3_test_access_key'
-  keystore 's3.client.repository_test_kit.secret_key', 's3_test_secret_key'
-  setting 's3.client.repository_test_kit.protocol', 'http'
-  setting 's3.client.repository_test_kit.endpoint', { "${-> fixtureAddress()}" }, IGNORE_VALUE
-
-  setting 'xpack.security.enabled', 'false'
+tasks.named('javaRestTest') {
+  usesDefaultDistribution()
 }
-

+ 33 - 9
x-pack/plugin/snapshot-repo-test-kit/qa/minio/src/javaRestTest/java/org/elasticsearch/repositories/blobstore/testkit/MinioSnapshotRepoTestKitIT.java

@@ -6,26 +6,50 @@
  */
 package org.elasticsearch.repositories.blobstore.testkit;
 
-import org.elasticsearch.common.settings.Settings;
+import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
 
-import static org.hamcrest.Matchers.blankOrNullString;
-import static org.hamcrest.Matchers.not;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.test.cluster.ElasticsearchCluster;
+import org.elasticsearch.test.cluster.local.distribution.DistributionType;
+import org.elasticsearch.test.fixtures.minio.MinioTestContainer;
+import org.elasticsearch.test.fixtures.testcontainers.TestContainersThreadFilter;
+import org.junit.ClassRule;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
 
+@ThreadLeakFilters(filters = { TestContainersThreadFilter.class })
 public class MinioSnapshotRepoTestKitIT extends AbstractSnapshotRepoTestKitRestTestCase {
 
+    public static final MinioTestContainer minioFixture = new MinioTestContainer();
+
+    public static ElasticsearchCluster cluster = ElasticsearchCluster.local()
+        .distribution(DistributionType.DEFAULT)
+        .keystore("s3.client.repository_test_kit.access_key", "s3_test_access_key")
+        .keystore("s3.client.repository_test_kit.secret_key", "s3_test_secret_key")
+        .setting("s3.client.repository_test_kit.protocol", () -> "http")
+        .setting("s3.client.repository_test_kit.endpoint", minioFixture::getAddress)
+        .setting("xpack.security.enabled", "false")
+        // Additional tracing related to investigation into https://github.com/elastic/elasticsearch/issues/102294
+        .setting("xpack.ml.enabled", "false")
+        .build();
+
+    @ClassRule
+    public static TestRule ruleChain = RuleChain.outerRule(minioFixture).around(cluster);
+
     @Override
     protected String repositoryType() {
         return "s3";
     }
 
     @Override
-    protected Settings repositorySettings() {
-        final String bucket = System.getProperty("test.minio.bucket");
-        assertThat(bucket, not(blankOrNullString()));
-
-        final String basePath = System.getProperty("test.minio.base_path");
-        assertThat(basePath, not(blankOrNullString()));
+    protected String getTestRestCluster() {
+        return cluster.getHttpAddresses();
+    }
 
+    @Override
+    protected Settings repositorySettings() {
+        final String bucket = "bucket";
+        final String basePath = "repository_test_kit_tests";
         return Settings.builder().put("client", "repository_test_kit").put("bucket", bucket).put("base_path", basePath).build();
     }
 }