Skip to content

Commit be6bdab

Browse files
Use TestFixturesPlugin to Run Minio in Tests (#37852)
* Use TestFixturesPlugin to Run Minio in Tests * Closes #37680 * Closes #37783
1 parent a3baa8f commit be6bdab

File tree

2 files changed

+29
-180
lines changed

2 files changed

+29
-180
lines changed

plugins/repository-s3/build.gradle

Lines changed: 20 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import org.apache.tools.ant.taskdefs.condition.Os
2-
import org.elasticsearch.gradle.LoggedExec
1+
import org.elasticsearch.gradle.BuildPlugin
32
import org.elasticsearch.gradle.MavenFilteringHack
43
import org.elasticsearch.gradle.test.AntFixture
54
import org.elasticsearch.gradle.test.ClusterConfiguration
65
import org.elasticsearch.gradle.test.RestIntegTestTask
76
import com.carrotsearch.gradle.junit4.RandomizedTestingTask
87

9-
import java.lang.reflect.Field
10-
118
/*
129
* Licensed to Elasticsearch under one or more contributor
1310
* license agreements. See the NOTICE file distributed with
@@ -139,25 +136,6 @@ if (!s3EC2Bucket && !s3EC2BasePath && !s3ECSBucket && !s3ECSBasePath) {
139136
throw new IllegalArgumentException("not all options specified to run EC2/ECS tests are present")
140137
}
141138

142-
143-
final String minioVersion = 'RELEASE.2018-06-22T23-48-46Z'
144-
final String minioBinDir = "${buildDir}/minio/bin"
145-
final String minioDataDir = "${buildDir}/minio/data"
146-
final String minioAddress = "127.0.0.1"
147-
148-
String minioDistribution
149-
String minioCheckSum
150-
if (Os.isFamily(Os.FAMILY_MAC)) {
151-
minioDistribution = 'darwin-amd64'
152-
minioCheckSum = '96b0bcb2f590e8e65fb83d5c3e221f9bd1106b49fa6f22c6b726b80b845d7c60'
153-
} else if (Os.isFamily(Os.FAMILY_UNIX)) {
154-
minioDistribution = 'linux-amd64'
155-
minioCheckSum = '713dac7c105285eab3b92649be92b5e793b29d3525c7929fa7aaed99374fad99'
156-
} else {
157-
minioDistribution = null
158-
minioCheckSum = null
159-
}
160-
161139
buildscript {
162140
repositories {
163141
maven {
@@ -169,177 +147,39 @@ buildscript {
169147
}
170148
}
171149

172-
private static int freePort(String minioAddress) {
173-
int minioPort
174-
ServerSocket serverSocket = new ServerSocket(0, 1, InetAddress.getByName(minioAddress))
175-
try {
176-
minioPort = serverSocket.localPort
177-
} finally {
178-
serverSocket.close()
179-
}
180-
if (minioPort == 0) {
181-
throw new GradleException("Could not find a free port for Minio")
182-
}
183-
return minioPort
184-
}
185-
186-
private int getMinioPid(Process minioProcess) {
187-
int minioPid
188-
if (JavaVersion.current() <= JavaVersion.VERSION_1_8) {
189-
try {
190-
Class<?> cProcessImpl = minioProcess.getClass()
191-
Field fPid = cProcessImpl.getDeclaredField("pid")
192-
if (!fPid.isAccessible()) {
193-
fPid.setAccessible(true)
194-
}
195-
minioPid = fPid.getInt(minioProcess)
196-
} catch (Exception e) {
197-
logger.error("failed to read pid from minio process", e)
198-
minioProcess.destroyForcibly()
199-
throw e
200-
}
201-
} else {
202-
minioPid = minioProcess.pid()
203-
}
204-
return minioPid
205-
}
206-
207-
private static Process setupMinio(String minioAddress, int minioPort, String minioDataDir, String accessKey, String secretKey,
208-
String minioBinDir, String minioFileName) {
209-
// we skip these tests on Windows so we do no need to worry about compatibility here
210-
final ProcessBuilder minio = new ProcessBuilder(
211-
"${minioBinDir}/${minioFileName}",
212-
"server",
213-
"--address",
214-
minioAddress + ":" + minioPort,
215-
minioDataDir)
216-
minio.environment().put('MINIO_ACCESS_KEY', accessKey)
217-
minio.environment().put('MINIO_SECRET_KEY', secretKey)
218-
return minio.start()
219-
}
220-
221-
private void addShutdownHook(Process minioProcess, int minioPort, int minioPid) {
222-
new BufferedReader(new InputStreamReader(minioProcess.inputStream)).withReader { br ->
223-
String line
224-
int httpPort = 0
225-
while ((line = br.readLine()) != null) {
226-
logger.info(line)
227-
if (line.matches('.*Endpoint.*:\\d+$')) {
228-
assert httpPort == 0
229-
final int index = line.lastIndexOf(":")
230-
assert index >= 0
231-
httpPort = Integer.parseInt(line.substring(index + 1))
232-
if (httpPort != minioPort) {
233-
throw new IllegalStateException("Port mismatch, expected ${minioPort} but was ${httpPort}")
234-
}
235-
236-
final File script = new File(project.buildDir, "minio/minio.killer.sh")
237-
script.setText(
238-
["function shutdown {",
239-
" kill ${minioPid}",
240-
"}",
241-
"trap shutdown EXIT",
242-
// will wait indefinitely for input, but we never pass input, and the pipe is only closed when the build dies
243-
"read line\n"].join('\n'), 'UTF-8')
244-
final ProcessBuilder killer = new ProcessBuilder("bash", script.absolutePath)
245-
killer.start()
246-
break
247-
}
248-
}
249-
250-
if (httpPort <= 0) {
251-
throw new IllegalStateException("httpPort must be > 0")
252-
}
253-
}
254-
}
255-
256-
if (useFixture && minioDistribution) {
257-
apply plugin: 'de.undercouch.download'
258-
259-
final String minioFileName = "minio.${minioVersion}"
260-
final String minioDownloadURL = "https://dl.minio.io/server/minio/release/${minioDistribution}/archive/${minioFileName}"
261-
final String minioFilePath = "${gradle.gradleUserHomeDir}/downloads/minio/${minioDistribution}/${minioFileName}"
150+
if (useFixture) {
262151

263-
task downloadMinio(type: Download) {
264-
src minioDownloadURL
265-
dest minioFilePath
266-
onlyIfModified true
267-
}
152+
apply plugin: 'elasticsearch.test.fixtures'
268153

269-
task verifyMinioChecksum(type: Verify, dependsOn: downloadMinio) {
270-
src minioFilePath
271-
algorithm 'SHA-256'
272-
checksum minioCheckSum
273-
}
274-
275-
task installMinio(type: Sync, dependsOn: verifyMinioChecksum) {
276-
from minioFilePath
277-
into minioBinDir
278-
fileMode 0755
154+
RestIntegTestTask integTestMinio = project.tasks.create('integTestMinio', RestIntegTestTask.class) {
155+
description = "Runs REST tests using the Minio repository."
279156
}
280157

281-
task startMinio {
282-
dependsOn installMinio
283-
284-
ext.minioPid = 0L
285-
ext.minioPort = 0
286-
158+
Task writeDockerFile = project.tasks.create('writeDockerFile') {
159+
File minioDockerfile = new File("${project.buildDir}/minio-docker/Dockerfile")
160+
outputs.file(minioDockerfile)
287161
doLast {
288-
new File("${minioDataDir}/${s3PermanentBucket}").mkdirs()
289-
290-
Exception accumulatedException = null
291-
for (int i = 0; i < 5; ++i) {
292-
try {
293-
minioPort = freePort(minioAddress)
294-
final Process process =
295-
setupMinio(minioAddress, minioPort, minioDataDir, s3PermanentAccessKey, s3PermanentSecretKey, minioBinDir, minioFileName)
296-
minioPid = getMinioPid(process)
297-
addShutdownHook(process, minioPort, minioPid)
298-
break
299-
} catch (Exception e) {
300-
logger.error("Exception while trying to start Minio {}", e)
301-
if (accumulatedException == null) {
302-
accumulated = e
303-
} else {
304-
accumulatedException.addSuppressed(e)
305-
}
306-
}
307-
}
308-
if (accumulatedException != null) {
309-
throw new GradleException("Failed to start Minio", accumulatedException)
310-
}
162+
minioDockerfile.parentFile.mkdirs()
163+
minioDockerfile.text = "FROM minio/minio:RELEASE.2019-01-23T23-18-58Z\n" +
164+
"RUN mkdir -p /minio/data/${s3PermanentBucket}\n" +
165+
"ENV MINIO_ACCESS_KEY ${s3PermanentAccessKey}\n" +
166+
"ENV MINIO_SECRET_KEY ${s3PermanentSecretKey}"
311167
}
312168
}
313169

314-
task stopMinio(type: LoggedExec) {
315-
onlyIf { startMinio.minioPid > 0 }
316-
317-
doFirst {
318-
logger.info("Shutting down minio with pid ${startMinio.minioPid}")
319-
}
320-
321-
final Object pid = "${ -> startMinio.minioPid }"
322-
323-
// we skip these tests on Windows so we do no need to worry about compatibility here
324-
executable = 'kill'
325-
args('-9', pid)
326-
}
327-
328-
RestIntegTestTask integTestMinio = project.tasks.create('integTestMinio', RestIntegTestTask.class) {
329-
description = "Runs REST tests using the Minio repository."
330-
}
331-
170+
preProcessFixture.dependsOn(writeDockerFile)
332171
// The following closure must execute before the afterEvaluate block in the constructor of the following integrationTest tasks:
333172
project.afterEvaluate {
334173
ClusterConfiguration cluster = project.extensions.getByName('integTestMinioCluster') as ClusterConfiguration
335174
cluster.dependsOn(project.bundlePlugin)
336-
cluster.dependsOn(startMinio) // otherwise we don't know the Minio port
175+
cluster.dependsOn(postProcessFixture)
337176
cluster.keystoreSetting 's3.client.integration_test_permanent.access_key', s3PermanentAccessKey
338177
cluster.keystoreSetting 's3.client.integration_test_permanent.secret_key', s3PermanentSecretKey
339178

340179
Closure<String> minioAddressAndPort = {
341-
assert startMinio.minioPort > 0
342-
return 'http://' + minioAddress + ':' + startMinio.minioPort
180+
int minioPort = postProcessFixture.ext."test.fixtures.minio-fixture.tcp.9000"
181+
assert minioPort > 0
182+
return 'http://127.0.0.1:' + minioPort
343183
}
344184
cluster.setting 's3.client.integration_test_permanent.endpoint', "${ -> minioAddressAndPort.call()}"
345185

@@ -354,8 +194,7 @@ if (useFixture && minioDistribution) {
354194
restIntegTestTask.clusterConfig.jvmArgs = jvmArgs
355195
}
356196

357-
integTestMinioRunner.dependsOn(startMinio)
358-
integTestMinioRunner.finalizedBy(stopMinio)
197+
integTestMinioRunner.dependsOn(postProcessFixture)
359198
// Minio only supports a single access key, see https://github.com/minio/minio/pull/5968
360199
integTestMinioRunner.systemProperty 'tests.rest.blacklist', [
361200
'repository_s3/30_repository_temporary_credentials/*',
@@ -364,6 +203,7 @@ if (useFixture && minioDistribution) {
364203
].join(",")
365204

366205
project.check.dependsOn(integTestMinio)
206+
BuildPlugin.requireDocker(integTestMinio)
367207
}
368208

369209
File parentFixtures = new File(project.buildDir, "fixtures")
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
version: '3'
2+
services:
3+
minio-fixture:
4+
build:
5+
context: ./build/minio-docker
6+
dockerfile: Dockerfile
7+
ports:
8+
- "9000"
9+
command: ["server", "/minio/data"]

0 commit comments

Comments
 (0)