Use TestFixturesPlugin to Run Minio in Tests (#37852)
* Use TestFixturesPlugin to Run Minio in Tests * Closes #37680 * Closes #37783
This commit is contained in:
parent
a3baa8f5ef
commit
be6bdab346
|
@ -1,13 +1,10 @@
|
||||||
import org.apache.tools.ant.taskdefs.condition.Os
|
import org.elasticsearch.gradle.BuildPlugin
|
||||||
import org.elasticsearch.gradle.LoggedExec
|
|
||||||
import org.elasticsearch.gradle.MavenFilteringHack
|
import org.elasticsearch.gradle.MavenFilteringHack
|
||||||
import org.elasticsearch.gradle.test.AntFixture
|
import org.elasticsearch.gradle.test.AntFixture
|
||||||
import org.elasticsearch.gradle.test.ClusterConfiguration
|
import org.elasticsearch.gradle.test.ClusterConfiguration
|
||||||
import org.elasticsearch.gradle.test.RestIntegTestTask
|
import org.elasticsearch.gradle.test.RestIntegTestTask
|
||||||
import com.carrotsearch.gradle.junit4.RandomizedTestingTask
|
import com.carrotsearch.gradle.junit4.RandomizedTestingTask
|
||||||
|
|
||||||
import java.lang.reflect.Field
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Licensed to Elasticsearch under one or more contributor
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
* license agreements. See the NOTICE file distributed with
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
@ -139,25 +136,6 @@ if (!s3EC2Bucket && !s3EC2BasePath && !s3ECSBucket && !s3ECSBasePath) {
|
||||||
throw new IllegalArgumentException("not all options specified to run EC2/ECS tests are present")
|
throw new IllegalArgumentException("not all options specified to run EC2/ECS tests are present")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final String minioVersion = 'RELEASE.2018-06-22T23-48-46Z'
|
|
||||||
final String minioBinDir = "${buildDir}/minio/bin"
|
|
||||||
final String minioDataDir = "${buildDir}/minio/data"
|
|
||||||
final String minioAddress = "127.0.0.1"
|
|
||||||
|
|
||||||
String minioDistribution
|
|
||||||
String minioCheckSum
|
|
||||||
if (Os.isFamily(Os.FAMILY_MAC)) {
|
|
||||||
minioDistribution = 'darwin-amd64'
|
|
||||||
minioCheckSum = '96b0bcb2f590e8e65fb83d5c3e221f9bd1106b49fa6f22c6b726b80b845d7c60'
|
|
||||||
} else if (Os.isFamily(Os.FAMILY_UNIX)) {
|
|
||||||
minioDistribution = 'linux-amd64'
|
|
||||||
minioCheckSum = '713dac7c105285eab3b92649be92b5e793b29d3525c7929fa7aaed99374fad99'
|
|
||||||
} else {
|
|
||||||
minioDistribution = null
|
|
||||||
minioCheckSum = null
|
|
||||||
}
|
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
|
@ -169,177 +147,39 @@ buildscript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int freePort(String minioAddress) {
|
if (useFixture) {
|
||||||
int minioPort
|
|
||||||
ServerSocket serverSocket = new ServerSocket(0, 1, InetAddress.getByName(minioAddress))
|
|
||||||
try {
|
|
||||||
minioPort = serverSocket.localPort
|
|
||||||
} finally {
|
|
||||||
serverSocket.close()
|
|
||||||
}
|
|
||||||
if (minioPort == 0) {
|
|
||||||
throw new GradleException("Could not find a free port for Minio")
|
|
||||||
}
|
|
||||||
return minioPort
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getMinioPid(Process minioProcess) {
|
apply plugin: 'elasticsearch.test.fixtures'
|
||||||
int minioPid
|
|
||||||
if (JavaVersion.current() <= JavaVersion.VERSION_1_8) {
|
|
||||||
try {
|
|
||||||
Class<?> cProcessImpl = minioProcess.getClass()
|
|
||||||
Field fPid = cProcessImpl.getDeclaredField("pid")
|
|
||||||
if (!fPid.isAccessible()) {
|
|
||||||
fPid.setAccessible(true)
|
|
||||||
}
|
|
||||||
minioPid = fPid.getInt(minioProcess)
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("failed to read pid from minio process", e)
|
|
||||||
minioProcess.destroyForcibly()
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
minioPid = minioProcess.pid()
|
|
||||||
}
|
|
||||||
return minioPid
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Process setupMinio(String minioAddress, int minioPort, String minioDataDir, String accessKey, String secretKey,
|
|
||||||
String minioBinDir, String minioFileName) {
|
|
||||||
// we skip these tests on Windows so we do no need to worry about compatibility here
|
|
||||||
final ProcessBuilder minio = new ProcessBuilder(
|
|
||||||
"${minioBinDir}/${minioFileName}",
|
|
||||||
"server",
|
|
||||||
"--address",
|
|
||||||
minioAddress + ":" + minioPort,
|
|
||||||
minioDataDir)
|
|
||||||
minio.environment().put('MINIO_ACCESS_KEY', accessKey)
|
|
||||||
minio.environment().put('MINIO_SECRET_KEY', secretKey)
|
|
||||||
return minio.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addShutdownHook(Process minioProcess, int minioPort, int minioPid) {
|
|
||||||
new BufferedReader(new InputStreamReader(minioProcess.inputStream)).withReader { br ->
|
|
||||||
String line
|
|
||||||
int httpPort = 0
|
|
||||||
while ((line = br.readLine()) != null) {
|
|
||||||
logger.info(line)
|
|
||||||
if (line.matches('.*Endpoint.*:\\d+$')) {
|
|
||||||
assert httpPort == 0
|
|
||||||
final int index = line.lastIndexOf(":")
|
|
||||||
assert index >= 0
|
|
||||||
httpPort = Integer.parseInt(line.substring(index + 1))
|
|
||||||
if (httpPort != minioPort) {
|
|
||||||
throw new IllegalStateException("Port mismatch, expected ${minioPort} but was ${httpPort}")
|
|
||||||
}
|
|
||||||
|
|
||||||
final File script = new File(project.buildDir, "minio/minio.killer.sh")
|
|
||||||
script.setText(
|
|
||||||
["function shutdown {",
|
|
||||||
" kill ${minioPid}",
|
|
||||||
"}",
|
|
||||||
"trap shutdown EXIT",
|
|
||||||
// will wait indefinitely for input, but we never pass input, and the pipe is only closed when the build dies
|
|
||||||
"read line\n"].join('\n'), 'UTF-8')
|
|
||||||
final ProcessBuilder killer = new ProcessBuilder("bash", script.absolutePath)
|
|
||||||
killer.start()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (httpPort <= 0) {
|
|
||||||
throw new IllegalStateException("httpPort must be > 0")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useFixture && minioDistribution) {
|
|
||||||
apply plugin: 'de.undercouch.download'
|
|
||||||
|
|
||||||
final String minioFileName = "minio.${minioVersion}"
|
|
||||||
final String minioDownloadURL = "https://dl.minio.io/server/minio/release/${minioDistribution}/archive/${minioFileName}"
|
|
||||||
final String minioFilePath = "${gradle.gradleUserHomeDir}/downloads/minio/${minioDistribution}/${minioFileName}"
|
|
||||||
|
|
||||||
task downloadMinio(type: Download) {
|
|
||||||
src minioDownloadURL
|
|
||||||
dest minioFilePath
|
|
||||||
onlyIfModified true
|
|
||||||
}
|
|
||||||
|
|
||||||
task verifyMinioChecksum(type: Verify, dependsOn: downloadMinio) {
|
|
||||||
src minioFilePath
|
|
||||||
algorithm 'SHA-256'
|
|
||||||
checksum minioCheckSum
|
|
||||||
}
|
|
||||||
|
|
||||||
task installMinio(type: Sync, dependsOn: verifyMinioChecksum) {
|
|
||||||
from minioFilePath
|
|
||||||
into minioBinDir
|
|
||||||
fileMode 0755
|
|
||||||
}
|
|
||||||
|
|
||||||
task startMinio {
|
|
||||||
dependsOn installMinio
|
|
||||||
|
|
||||||
ext.minioPid = 0L
|
|
||||||
ext.minioPort = 0
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
new File("${minioDataDir}/${s3PermanentBucket}").mkdirs()
|
|
||||||
|
|
||||||
Exception accumulatedException = null
|
|
||||||
for (int i = 0; i < 5; ++i) {
|
|
||||||
try {
|
|
||||||
minioPort = freePort(minioAddress)
|
|
||||||
final Process process =
|
|
||||||
setupMinio(minioAddress, minioPort, minioDataDir, s3PermanentAccessKey, s3PermanentSecretKey, minioBinDir, minioFileName)
|
|
||||||
minioPid = getMinioPid(process)
|
|
||||||
addShutdownHook(process, minioPort, minioPid)
|
|
||||||
break
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Exception while trying to start Minio {}", e)
|
|
||||||
if (accumulatedException == null) {
|
|
||||||
accumulated = e
|
|
||||||
} else {
|
|
||||||
accumulatedException.addSuppressed(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (accumulatedException != null) {
|
|
||||||
throw new GradleException("Failed to start Minio", accumulatedException)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task stopMinio(type: LoggedExec) {
|
|
||||||
onlyIf { startMinio.minioPid > 0 }
|
|
||||||
|
|
||||||
doFirst {
|
|
||||||
logger.info("Shutting down minio with pid ${startMinio.minioPid}")
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object pid = "${ -> startMinio.minioPid }"
|
|
||||||
|
|
||||||
// we skip these tests on Windows so we do no need to worry about compatibility here
|
|
||||||
executable = 'kill'
|
|
||||||
args('-9', pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
RestIntegTestTask integTestMinio = project.tasks.create('integTestMinio', RestIntegTestTask.class) {
|
RestIntegTestTask integTestMinio = project.tasks.create('integTestMinio', RestIntegTestTask.class) {
|
||||||
description = "Runs REST tests using the Minio repository."
|
description = "Runs REST tests using the Minio repository."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Task writeDockerFile = project.tasks.create('writeDockerFile') {
|
||||||
|
File minioDockerfile = new File("${project.buildDir}/minio-docker/Dockerfile")
|
||||||
|
outputs.file(minioDockerfile)
|
||||||
|
doLast {
|
||||||
|
minioDockerfile.parentFile.mkdirs()
|
||||||
|
minioDockerfile.text = "FROM minio/minio:RELEASE.2019-01-23T23-18-58Z\n" +
|
||||||
|
"RUN mkdir -p /minio/data/${s3PermanentBucket}\n" +
|
||||||
|
"ENV MINIO_ACCESS_KEY ${s3PermanentAccessKey}\n" +
|
||||||
|
"ENV MINIO_SECRET_KEY ${s3PermanentSecretKey}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
preProcessFixture.dependsOn(writeDockerFile)
|
||||||
// The following closure must execute before the afterEvaluate block in the constructor of the following integrationTest tasks:
|
// The following closure must execute before the afterEvaluate block in the constructor of the following integrationTest tasks:
|
||||||
project.afterEvaluate {
|
project.afterEvaluate {
|
||||||
ClusterConfiguration cluster = project.extensions.getByName('integTestMinioCluster') as ClusterConfiguration
|
ClusterConfiguration cluster = project.extensions.getByName('integTestMinioCluster') as ClusterConfiguration
|
||||||
cluster.dependsOn(project.bundlePlugin)
|
cluster.dependsOn(project.bundlePlugin)
|
||||||
cluster.dependsOn(startMinio) // otherwise we don't know the Minio port
|
cluster.dependsOn(postProcessFixture)
|
||||||
cluster.keystoreSetting 's3.client.integration_test_permanent.access_key', s3PermanentAccessKey
|
cluster.keystoreSetting 's3.client.integration_test_permanent.access_key', s3PermanentAccessKey
|
||||||
cluster.keystoreSetting 's3.client.integration_test_permanent.secret_key', s3PermanentSecretKey
|
cluster.keystoreSetting 's3.client.integration_test_permanent.secret_key', s3PermanentSecretKey
|
||||||
|
|
||||||
Closure<String> minioAddressAndPort = {
|
Closure<String> minioAddressAndPort = {
|
||||||
assert startMinio.minioPort > 0
|
int minioPort = postProcessFixture.ext."test.fixtures.minio-fixture.tcp.9000"
|
||||||
return 'http://' + minioAddress + ':' + startMinio.minioPort
|
assert minioPort > 0
|
||||||
|
return 'http://127.0.0.1:' + minioPort
|
||||||
}
|
}
|
||||||
cluster.setting 's3.client.integration_test_permanent.endpoint', "${ -> minioAddressAndPort.call()}"
|
cluster.setting 's3.client.integration_test_permanent.endpoint', "${ -> minioAddressAndPort.call()}"
|
||||||
|
|
||||||
|
@ -354,8 +194,7 @@ if (useFixture && minioDistribution) {
|
||||||
restIntegTestTask.clusterConfig.jvmArgs = jvmArgs
|
restIntegTestTask.clusterConfig.jvmArgs = jvmArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
integTestMinioRunner.dependsOn(startMinio)
|
integTestMinioRunner.dependsOn(postProcessFixture)
|
||||||
integTestMinioRunner.finalizedBy(stopMinio)
|
|
||||||
// Minio only supports a single access key, see https://github.com/minio/minio/pull/5968
|
// Minio only supports a single access key, see https://github.com/minio/minio/pull/5968
|
||||||
integTestMinioRunner.systemProperty 'tests.rest.blacklist', [
|
integTestMinioRunner.systemProperty 'tests.rest.blacklist', [
|
||||||
'repository_s3/30_repository_temporary_credentials/*',
|
'repository_s3/30_repository_temporary_credentials/*',
|
||||||
|
@ -364,6 +203,7 @@ if (useFixture && minioDistribution) {
|
||||||
].join(",")
|
].join(",")
|
||||||
|
|
||||||
project.check.dependsOn(integTestMinio)
|
project.check.dependsOn(integTestMinio)
|
||||||
|
BuildPlugin.requireDocker(integTestMinio)
|
||||||
}
|
}
|
||||||
|
|
||||||
File parentFixtures = new File(project.buildDir, "fixtures")
|
File parentFixtures = new File(project.buildDir, "fixtures")
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
minio-fixture:
|
||||||
|
build:
|
||||||
|
context: ./build/minio-docker
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
ports:
|
||||||
|
- "9000"
|
||||||
|
command: ["server", "/minio/data"]
|
Loading…
Reference in New Issue